查询优化是查询编译过程中的一个环节,他负责把以某种高级语言写出的数据操作语句转成一个更加详尽的过程化的操作符序列,这个序列就是所谓的查询计划。
select ->查询解析器–>查询优化器—>代码生成解释器---->查询处理器----->得到查询结果
进行查询优化的4个基本技术:
mysql是一个混合使用多种优化技术的数据库系统。mysql查询优化是围绕“选取–投影–联结”策略进行的。综合了基于开销的优化器和启发式优化器的优点,生成查询计划相随较少。然后在利用基于开销的优化技术从中选出一个最短的执行路径。
索引可以加快查询的技术有很多,其中最重要的是索引,通常能够使得查询速度照成差异化。当查询速度很慢时,添加上索引后就能够迅速解决问题。
索引可以提高搜索效率的第一个原因就是我们可以得知匹配数据行在什么位置结束,从而跳过其余部分,
mysql使用索引的方式有以下几种:
如果不需要某个特定的索引加快查询速度就不要创建他。
select
col_a <-----a candidate
from
tab1 left join tb2
on tab1.col_b = tab12.col_c <-- candidates
where
col_d=expr <—a candidate
综合考虑各数据列的维度。
数据列的维度等于他所能容纳的非重复值的个数。数据列的维度越高,他包含的独一无二的值就越多,重复值就越少,索引的效果就越好。
查询优化程序确定出某个数值在数据表中的数据行中出现的频率超过30%时查询优化就会跳过索引。进行全表扫描。现如今的优化器更复杂,能够把其他因素也考虑过来,所以这个百分比已经不再是mysql决定进行一次扫描而不使用一个索引的唯一依据了
对短小的值进行索引。
尽量选用小的数据类型,比如你的数据没有一个比25个字符更长,就不要选用char(100).比较短小的值可以从以下几个方面提高索引的处理性能。
短小的值可以让操作更快完成,加快索引查找速度。
短小的值可以让索引的“体积”更小,减少磁盘I/O活动
短小的键值意味着缓存里的索引可以容纳更多的键。
为字符串值的前缀编排索引。
充分利用最左边的前缀。
当创建一个n个数据列的复合索引时,复合索引 相当于n个索引,因为索引的最左边的数据列集合能够用于匹配数据行,这样的一个集合称为:最左边索引。
适可而止,不要建立过多的索引。
让索引的类型与你打算进行比较操作的类型保持匹配。
利用慢查询日志找出性能劣质的查询。
EXPLAIN SELECT * from domains_domain where isDeleted=0
id | selete_type | table | partitions | type | possible_keys | key-len | ref | rows | filtered | Extra | |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | domains_domain | all | 75203 | 10 | using where |
把结果放在临时表里。
若union包含在from子句的子查询中,外层select将被标记为:derived
所操作的表
字段表明优化器可以使用索引来搜索一个特定区间的值。
性能:system > const > eq_ref > ref > range > index > all
全版:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > all
一般保证查询至少达到range级别,最好能达到ref
显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
实际使用的索引。如果为NULL,则没有使用索引。查询中若使用了覆盖索引,则该索引仅出现在key列表中。
表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好。
key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。
包含不适合在其他列中显示但十分重要的额外信息
查询优化器主要的目的是只要对可能就要使用索引,并且要使用条件最严格的索引来尽可能多,尽可能快地排除那些不符合索引条件的数据行。
这将生成关于索引值分情况的统计数据,他们可以帮助优化器对索引的使用效果做出更准确的评估。如果数据表经常更新就应该对其不时地进行分析;如果某数据填充好就不在发生变化,只需在加载后对其做一次分析就够了。
expain语句会告诉对定的查询有没有使用索引
在连接时可以对数据表名字后面利用 force index ,use index或ignore index限定词告诉服务器想使用哪些索引。
对带有索引的数据列进行比较时,如果特闷数据类型相同,查询性能就会高一些,如果查询类型不同,查询性能就会低一些。
如果你在函数调用中使用数据列,或者将数据列作为算术运算表达式中很复杂的项目的一部分,mysql将不能使用索引。因为它必须要对每个数据列计算出表达式的值。
这个索引不能使用:select * from mytab where Year(data_col) <1990; 这时比较的时必须计算出数据列的值。完成整个计算结果数据列data_col的索引就不能使用,会进行全表扫描,必须使用一个准确的日期表示方法 where data_col<‘1990-01-01’
这个索引不能使用:where TO_DAYS(date_col) - TO_DAYS(curDate()) < cutoff 因为数据列的每行都要检索才能计算出TO_DAYS(date_col)的值
这个索引不能使用:where TO_DAYS(date_col)
这个索引能使用:where date_col < DATE_ADD(currdate(), INTERVAL cutoff DAY) 这样是让日期值与数据列比较不再转换成天数,可以使用索引
where col_name like ‘%string%’ 语句是正确的,但不要出于习惯将符号“%”放置字符串两侧、
匹配“MAC姓氏开头的”macGre mascD
where col_name like ‘string%’ 时优化程序看到了模式是字符开始部分会使用索引行,这样好像是就是 where las_name >=‘mac’ and last_name <‘mad’
这种优化不能使用在Regexp操作表达式中,regexp表达式不能被优化
Mysql支持联结查询和子查询,联结查询优化效果比对子查询的优化效果更好。
当试验一个查询的变化2格式时每一种方式都要多运行几次。
mysql能够实现自动类型转换,但是如果能避免这些转换,
select * from mytb1 where num_col= 4;
select * from mytb1 where num_col=‘4’ ; 包含数据转换转换,如果数据列num_col有索引,那么含有类型转换的比较有可能阻止索引得到试用、
数值运算比字符运算快的多。数值之间的比较只需要一个操作就可以完成,而字符串之间的比较一般需要进行多次字节与字节或字符与字符的比较才能完成,而且字符串比越长,比较次数就越多。
小类型比大类型的处理速度更快,字符串处理为时与他们得长度呈正比关系。选用小的数据类型可以使得整个数据表更小,从小减少磁盘读写开销,对于数据列有索引的,使用较短的数据值还将进一步提升。短索引值处理速度比长索引值的处理更快。
数据列声明not null 时,对他的处理可以更快的完成。查询期间不再会检查数据列值是不是null了。
select * from tab1_name procedure analyse()
根据数据表里的其他数据列计算出一个散列值并将它来另外保存一个数据列然后通过搜索散列值去找,这里只适合精确匹配查询。Md5(),SHA1() CRC32()函数生成散列值
当不需要查询出大的字段时建议不要查出。
mysql的默认调度策略综述如下:
mysql提供了一些语句修饰符来改变他的调度策略。一是在delete,insert,load data, replace和update语句使用low_priority关键字,二是在select和insert语句使用high_priority关键字,三是在insert和replace语句中使用delayed关键字。
low_priority和high_priority限定符只对支持数据表锁定功能的存储引擎。有效果,delayed限定符在myISAM,MEMEORY,ARCHIVE和BLACKHOLE存储引擎上都可以使用。
low_priority关键字影响delete,insertmload_data,replace和update语句的调度。
写等待:当一个数据表正在读取时来了一个写的操作,则写操作就会等待读操作完成之后。默认的调度策略是写入者比读取者优先
对于high_priority关键字的select查询,情况也是类似。允许select查询操作插入正在等待的写入操作之前。即使通常情况下写入操作有较高的优先。另外一个高优先的select将先于普通的select语句执行。
delayed修饰符用在insert和replace语句中,当delayed请求到达数据表时,服务器将数据行排序并且迅速地返回到客户程序的状态,从而使客户程序可以在数据行被插入之前进行。
并发插入应注意以下问题。