问题起因:
一个存在很久的一个查询接口,在做了一次性能优化改动之后,发现查询结果的排序偶尔出现混乱的情况(客户现场混乱,本地测试正常)
问题分析:
将客户现场偶然出现混乱的数据导入本地数据库,调用该查询接口,发现这个问题使用该客户数据必现,直接数据库使用该接口的SQL语句进行查询,发现同样有该问题的存在,断定是SQL优化导致的该问题
问题解决:
经排查,该接口优化以后开发去掉了order by,想仅通过走索引排序。问题来了,加索引不代表会用索引,数据库走执行计划是依据统计信息计算算出来的,统计信息是抽样获得的,当带查询条件的查询数据使用索引和全表扫描的开销差不多或者全表扫描的开销更快的时候,数据库会直接使用全表扫描的执行计划,不会走索引,全表扫描使用的就是数据库的默认排序,应该是根据数据块(索引块)内记录的物理顺序展示的,所以接口查询出来的数据不一定符合我们的预期排序结果。
举例:
下图Order1表总数据量是109997条,num>0的是109997条,num<40的是75条。
接下来我们可以看一下109997条和75条的执行计划的不同。
可以很清楚的看到select * from Order1 where num>0 的SQL走的全表扫描,select * from Order1 where num<40的SQL走的索引查找
最后这种需要返回排序结果的查询接口,建议要么再SQL语句后加order by,要么在代码里面进行排序后返回结果。我们项目目前采取的是第一种方案
PS:
1、索引起不起作用有很多因素,我这个例子里面,数据量是唯一因素,因为其他变量都没有变化,只有数据量的变化
2、我们本地测试没有问题是因为刚好做业务产生的数据与物理存储一致,走数据库默认排序也没发现这个问题。