最近在做mysql数据库的一些优化,主要是sql语句的优化。查阅了一些资料加上一些实战,这里简单做一下总结,水平有限,欢迎大家指正:
?
sql优化,一般有两方面:
?
优化io:
?
IO应该是数据库(尤其是数据量比较大的时候)时间开销最大的地方了,所以,IO优化非常重要,我们常用的方法是通过合理的使用索引来减少IO。
?
减少cpu运算:
?
除了IO,减少cpu运算也是一个优化sql的有效手段。order by,,group by,distinct,count …等都是比较消耗cpu的操作,但是,有时候为了更方便的得到想要的查询结果,这些操作还是必须有的。怎么办呢,其实,有时候我们可以将一些操作在程序里 实现,比如,我们有时候将两个表的中间结果放在map或者set中,通过简单的循环进行完成匹配,或者去重等操作。
?
我们的工作环境用的是 innodB,其实,我们用到的优化方式主要就是 先查看sql的执行计划,找出性能瓶颈,然后更合理的使用索引、选择更合适的语句过滤条件、用更轻快的查询替换容易导致查询中间结果臃肿的查询。
?
通过 explain+sql? 我们可以了解sql 的执行计划,通过sql的执行计划,可以了解查询的性能瓶颈,简单对 explain 结果进行说明一下:
?
执行计划包含的信息有:
?
?
1、id:
?
?????????? 表示查询中执行select子句或操作表的顺序
?
??????????
?
??????????? 如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行。
?
??????????? id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行。
?
?
?
2、select_type:
?
? ? ?? 表示查询中每个select子句的类型,可以理解为语句的复杂程度。
?
? ? ? ?? ?????
?
??????????????? SIMPLE:比较简单,查询中不含子查询或UNION
?
???????????????? PRIMARY:若查询中包含子查询或UNION等,最外层查询为PRIMARY
?
???????????????? SUBQUERY:在SELECT 或者 WHERE 后面跟的子查询,该子查询为SUBQUERY
?
???????????????? DERIVED:在FROM后面的子查询为 DIRIVED
?
???????????????? UNION:出现在UNION之后的SELECT,被标记为UNION
?
???????????????? UNION RESULT:从UNION表获取结果的SELECT会被标记为UNION RESULT
?
? ? ? ? ? ? ? ?? 还有一种相关子查询:
?
? ? ? ? ? ? ? ?? DEPENDENT SUBQUERY:是指引用了外部查询列的子查询,即子查询会对外部查询的每行进行一次计算。 ??????????????
?
3、type:
?
? ? ? ? ? ? ? ?? 查询mysql表的方式,又称“访问类型”:
?
? ? ? ? ? ? ? ??
?
?????????????????? 一般来说,从左向右,性能有差到好,但是,有时候强制使用不恰当的索引(ref)性能反而不如全表扫描(ALL)
?
4、possible_keys:
?
??????????????????? mysql可能使用的索引。
?
5、key:
?
??????????????????? 在查询中实际用的索引。
?
6、key_len:
?
??????????????????? 表示实际使用的索引的字节数,可通过该列计算查询中使用的索引长度,该值是通过索引定义计算得来。
?
7、ref:
?
??????????????????? 表示查询中表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。
?
????????????????????
?
????????????????????? 上面例子中:t1的col1匹配t2表的col1,col2匹配了一个常量(const)‘ac’,
?
8、rows:
?
????????????????????? 表示mysql根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。这一项很重要,它基本能看出sql语句所要查询的行数,直观的显示了sql语句和使用索引的好坏。
?
9、Extra:
?
????????????????????? 包含不适合在其他列中显示但是很重要的额外信息。
?
?????????????????????? a、Using index
?
????????????????????????????? 表示相应的select操作中使用了覆盖索引。
?
????????????????????????????? 覆盖索引:表示包含所有满足查询需要的数据的索引。可以利用索引返回select要选的列表中的字段,而不必根据索引再次读取数据文件。
?
????????????????????????????????????????????????? 如果要使用覆盖索引,一定要注意select列表中只需取出需要的列,不可select * ,因为将所有字段一起做索引会导致索引文件过大,查询性能?????
?
????????????????????????????????????????????????? 下降。
?
????????????????????? b、Using where:
?
??????????????????????????? 表示mysql服务器在存储引擎收到记录后进行 “后过滤”,如果查询没有使用索引,Using where的作用只是提醒我们mysql将用where子句来过滤结果集。
?
????????????????????? c、Using temporary:
?
??????????????????????????? 表示mysql需要使用临时表来存储结果集,常见于order by和group by操作。
?
????????????????????? d、Using filesort:
?
???????????????????????????? mysql中无法利用索引完成的排序操作称为“文件排序”。
?
???????????????????????????? 它不是使用排序的临时表太大导致内存放不下,从而放到硬盘上的“文件排序”,它只是排序(不用索引)。
?
另外,还可以使用 慢查询 和 profile 来查看sql语句的 磁盘IO和内存IO。现在我也不太了解,以后学习到了再为大家说明。
?
下面,我们说一下sql语句的执行顺序:
?
???????????????????? mysql 的sql 语句 执行顺序:
?????????????????? (8)SELECT (9) DISTINCT<select_list>
?????????????