最近遇到一个sql优化的场景,记录分享一下。
下图是我们服务的详情页, 出现的问题是什么呢?在用户查询发送短信详情的情况下,用户的页面请求迟迟不反回,然后报错。

问题的原因是什么呢,保障的客户是我们服务的大客户,消息量非常大, 目前为止已经这张详情表已经有5千万左右的数据量。这个页面我们的处理有两个,一个是查数据,另一个就是count一个总条数, 在现网分别分析了下两条sql都在几百秒。因此问题很明显在sql这两条语句上面, 那么一个一个分析。
第一条慢sql如下
1 | SELECT ENDPOINT, NATION_CODE, MESSAGE_ID, SIGN_ID, CREATE_TIME, DELIVER_TIME, STATUS, CODE WHERE OWNER_ID = ? AND CREATE_TIME > ? AND CREAT_TIME < ? ORDER BY ID DESC LIMIT ? OFFSET ?; |
这张表当前索引情况: 、、、、
explan 发现 seq scan, 没命中索引, 在这种数据量下全表扫肯定不行。另一个问题是这个表的排序用的是quicksort, 理论上b+tree是递增排序的,因此可以省去排序的时间。
解决办法
1. 添加一条(CREAT_TIME, OWNER_ID)的联合索引
2. Order by ID DESC 改为 Order by CREAT_TIME DESC
改第一条的原因是因为主要产生筛选作用的是CREATE_TIME, 为了命中索引因此做这个改进。
改第二条的原因是当Order by 的关键字在Where中有, 才不会filesort.
第二条慢sql
产生第二条慢sql的原因就是因为使用count, 对于带where的count的sql语句的优化空间非常小,因为是实时的计数,扫描数据量根据查询范围可能非常大。
解决办法
这块的解决办法有很多, 首先使用缓存count是不行的,因为查询中带实时性。那么剩下的解决办法就是去掉这个count,不给用户反馈了。