mysql 优化实例演示


mysql 优化实例演示

针对表ueb_ebay_message_send(myisam和innodb引擎的索引默认是B-tree索引)

 根据从正式服务器上抓取的超过2s的慢查询,先通过explain来看看查询计划

测试一

原始语句:

explain select pid,recipientid,itemid,content,opration_date,upload_status,opration_id,upload_date,ebay_accountid from ueb_ebay_message_send  where 1  and `opration_id`='肖双梅' and date_format(`opration_date`,'%Y-%m-%d')='2017-06-06'    limit 0,25;

执行计划如下图

type=ref,key=IX_ opration_id,ref=const,rows=93476

测试二

我按照查询条件,使用常用的办法,先使用语句加一个索引:

create index IX_ opration_date on ueb_ebay_message_send(opration_date, opration_id(10));

然后再查看查询计划,索引无效,

type=ref,key=IX_ opration_id,ref=const,rows=93576

结果发现新建的索引没有任何效果,这里证实了一个问题,date_format函数会影响mysql查询分析器对索引的正确判断。

测试三

强制查询走IX_opration_date索引

explain select pid,recipientid,itemid,content,opration_date,upload_status,opration_id,upload_date,ebay_accountid from ueb_ebay_message_send force index(IX_opration_date)  where 1  and `opration_id`='肖双梅' and date_format(`opration_date`,'%Y-%m-%d')='2017-06-06'    limit 0,25;

强制使查询分析器走IX_ opration_date索引。查看查询计划,发现mysql查询分析器连索引都不走了,全表扫描,即使强制制定使用新建的索引mysql都不予理会。

type=ALL,key=NULL,ref=NULL,rows= 1281658

测试四

修改一下语句,不用date_format函数,不强制使用索引

explain select pid,recipientid,itemid,content,opration_date,upload_status,opration_id,upload_date,ebay_accountid from ueb_ebay_message_send  where 1  and `opration_id`='肖双梅' and opration_date<'2017-06-07 00:00:00' and  opration_date>'2017-06-05 23:59:59'  limit 0,25;

查看查询计划,查询计划有变化了,使用到了新索引。

type=range,key= IX_opration_date,ref=NULL,rows=11266

在这里小结一下,rows=11266这个为了得到这个结果,mysql只需要扫描11266行,这是目前为止,mysql效率最高的查询计划,遗憾的是type=range,范围扫描,这个有点拉低了查询效率。

测试五

我重新再建立一个索引,只是把IX_opration_date索引的字段调换一下位置。

CREATE INDEX IX_opration_id_opration_date ON ueb_ebay_message_send(opration_id(10),opration_date);

再次从测试一的语句开始测试

type= ref,key= IX_opration_id_opration_date,ref=const,rows= 76473

这里可以看出来,查询效率低于测试四。虽然type变成ref了,但是rows值变大了很多,反而效率低了。

测试六

这个时候我使用测试四的语句再看看查询计划。

type=range,key= IX_opration_date,ref=NULL,rows=224

此时,rows 值才224行,效率一下就提升上来了。

总结:

1、使用DATE_FORMAT之类的函数对表字段计算,会导致mysql放弃相匹配的索引。

2、再进行范围查询时,如果where条件中还有其他字段等于某个值。那么建立索引时,索引字段顺序需要把范围查询字段放在索引字段的最后。

3、上面测试,针对的索引出现了多余,比如IX_ opration_id, IX_opration_id_opration_date,前一个索引只有一个字段,后一个索引有两个字段,但是他们的第一个字段都是一样的,那么第一个索引适用的范围更小,可以删除掉。