关于mysql 使用or连接索引失效引起的慢查询优化的初步实践
2016-12-26 17:18
1026 查看
最近在使用mysql开发时候,遇到稍微多数据时候,sql查询中的order by 语法的查询效率明显的降低了好几个数量级,所以进行了一些sql语句调整或者说是简单优化的尝试。仅供大家参考,或者说是为大家提供一个尝试的思路。 (ps:数据库部署在阿里云服务上,mysql版本5.6,下面sql查询的还仅仅是前15条记录/页) 查询的表就是很常见的商户表(t_merchants)和店铺表(t_shops),sql查询目的是:根据查询条件,查询店铺表,再根据店铺表中关联的商户id将所有的商户信息查询出来,其中,也包括未关联店铺(也就是说商户表中店铺数量字段值为0)的商户。一个商户对应多家店铺,sql如下:
SELECT DISTINCT m.i_id MERCHANTID, m.vc_merchants_name MERCHANTNAME, m.vc_address DETAILADDR, m.i_shop_num SHOPNUM FROM t_merchants m, t_shop s where ( m.i_id = s.i_merchants_id OR m.i_shop_num=0) AND m.i_id IS NOT NULL AND s.i_state != 4 AND m.i_state !=3 ORDER BY m.vc_create_time DESC limit 1,10
也就是几百条数据,执行查询居然花费了7s左右(当然,也可能是自身的硬件配置太低也有影响哈哈)。使用explain查询执行过程如下图:
可以看到,是两个表都进行了全表扫描。其中商户表的i_state,vc_create_time和店铺表的i_state,i_merchants_id都是索引列。但是从执行计划看到,并没有用到索引,即索引失效了,主要的问题在于where连接后面的or m.i_shop_num=0这个查询条件,引起索引失效。
*若是将连接条件中“OR m.i_shop_num=0”去掉的话,平均查询时间花费也就是30毫秒左右而已,可见mysql的order by消耗大部分查询时间。
++++++++++++++++++
那么如何能让索引生效呢,就想通过子查询来进行尝试:开始仅仅是通过子查询查询商户表的主键i_id,不需要将商户表的其他字段内容查询出来,第二步通过in语法再次查询商户表的具体字段记录。sql如下:
SELECT m.i_id MERCHANTID, m.vc_merchants_name MERCHANTNAME, m.vc_address DETAILADDR, m.i_shop_num SHOPNUM FROM t_merchants m where m.i_id in ( SELECT DISTINCT m1.i_id from t_merchants m1, t_shop s where ( m1.i_id = s.i_merchants_id OR m1.i_shop_num=0 ) and m1.i_id IS NOT NULL AND s.i_state != 4 AND m1.i_state !=3 ) ORDER BY m.vc_create_time DESC limit 1,15
查询时间花费60ms左右,相比刚开始的6s、7s而言(>-<||||),那就不用解释了。使用explain查询执行过程如下图:
在商户表和店铺表之间,内部嵌套了一个eq_ref类型扫描查询。所以,大部分的性能提升应该跟它有些关系了。从执行计划中看到,使用了eq_ref唯一索引进行查询扫描,所以速度就上来了。
关于eq_ref的介绍,个人感觉这篇文章介绍挺好:
http://www.cnblogs.com/heat-man/p/4945708.html
所以在写sql时候,可以用explain来查看执行效率,也要注意当where条件后面使用or 后面加上不是索引列的字段,会使得查询不走索引,速度会慢下来,至于更内部原因,还要不断深入学习…..
相关文章推荐
- MySQL查询优化技术系列讲座之使用索引
- MySQL查询优化技术系列讲座之使用索引
- 关于mysql inner join 连接查询的优化
- MySQL性能优化的21个最佳实践 和 mysql使用索引(转)
- 关于Mysql模糊查询的优化-全文检索和Like的使用
- MySQL查询优化技术之使用索引
- MySQL性能优化的21个最佳实践 和 mysql使用索引【转载】
- MySQL性能优化的21个最佳实践 和 mysql使用索引
- MySQL查询优化技术系列讲座之使用索引(一)
- MYSQL查询优化:使用索引
- 使用连接(JOIN)来代替子查询(Sub-Queries) mysql优化系列记录
- MySQL查询优化讲座之使用索引
- MySQL查询优化技术系列讲座之使用索引【转】
- 使用连接(JOIN)来代替子查询(Sub-Queries) mysql优化系列记录
- 使用连接(JOIN)来代替子查询(Sub-Queries) mysql优化系列记录
- MySQL查询优化技术系列讲座之使用索引
- MySQL性能优化的21个最佳实践 和 mysql使用索引(转)
- MYSQL查询优化:使用索引
- MYSQL查询优化:使用索引
- MySQL性能优化的21个最佳实践 和 mysql使用索引