查询优化
1、explain查询分析器,查看执行计划
2、索引的设计
3、慢查询日志,调试环境可以开启
4、查询缓存,区分业务,不经常变更的业务可以开启
show global status like 'QCache%';
show global status like 'Com_select';
查询缓存命中率 = Qcache_hits/(Qcache_hits + Com_select),
查询缓存命中率多大才是好的命中率,需要具体情况具体分析。
推荐一个指标:”命中和写入“的比率,即Qcache_hits和Qcache_inserts的比值。
根据经验来看,当这个比值大于3:1时通常查询缓存是有效的,如果能达到10:1最好
索引设计
1、在经常用作where条件和group/order by的字段上建立索引
2、最左前缀匹配原则
3、尽量选择区分度高的列作为索引
4、索引列不能参与运算,如date(update_time) 这样是用不到索引的
5、尽量扩展索引,不要新建索引
索引最左匹配原则
mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配
比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。即,组合索引的第一个字段必须出现在查询组句中,这个索引才会被用到。
解释:(a,b,c,d)的索引,索引匹配顺序a-b-c-d,而由于where c >3停止匹配,所以d就用不到索引了
(a,b,d,c)的索引,索引匹配顺序a-b-d-c,为何可以用到d了呢,注意最左匹配说的是索引的匹配,并不是where条件的顺序
设计优化
1、数据库字段的设计,适度冗余字段,避免join
2、做分库分表
3、分库分表的ER表的设计,例如order-orderdetail,同一个订单号落在同一个库中
4、跨库join,通过建立全局表,冗余字段来避免
EXPLAIN
possible_keys:表示搜索可能用到的索引
key:表示实际选用的索引,如果没有选择索引,是NULL
有一种可能是possible_keys为空,但是key不为空的情况。
这种情况下说明mysql无法利用索引来搜索数据,但是返回的列却是某个索引的一部分,因此可以用覆盖索引的方式优化全表扫描。
https://ruby-china.org/topics/27022 末尾的评论
key_len:显示MySQL决定使用的键长度,如果键是NULL,则长度为NULL
如,字段a(int 4) b(int 3),查询时只用到复合索引(a,b)中的a,则key_len=4,实际使用的键的字节长度,若两个都用到了key_len=7
rows:显示MySQL认为它执行查询时必须检查的行数。多行之间的数据相乘可以估算要处理的行数。
ref:ref列显示哪些列或常量与键列中指定的索引进行比较,即显示索引的哪一列被使用了
type:连接类型
从最好到最差的连接类型为 const、eq_reg、ref、range、index和ALL
const:最多有一行匹配,如使用RIMARY KEY or UNIQUE index作为条件查询时
eq_ref:对于每个来自于前面的表的行组合,从该表中读取一行。除了system(只有一行)和const类型,这是最好的连接类型。
ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取
..
index:该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
ALL:对于每个来自于先前的表的行组合,进行完整的表扫描。
filtered:显示了通过条件过滤出的行数的百分比估计值
参考:
https://tech.meituan.com/mysql-index.html
https://www.zhihu.com/question/36996520
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
http://blog.csdn.net/mccand1234/article/details/66475382
http://overtrue.me/articles/2014/10/mysql-explain.html
https://ruby-china.org/topics/27022