有一个表 TableA,数据量很大,约 4000w 条。 使用 where 条件,where TableA.columnA='value'后,可以查出约 70w 条数据。 现在有个业务逻辑: 想在 TableA 中使用 where 条件 where TableA.columnA='value'查询数据,并且将数据按照时间戳排序,所以最后的 sql 是: select * from TableA where TableA.columnA='value' order by timestamp; 通过 explain 发现,此次执行是一个 simple 查询,扫描了全表 4000w 数据(columnA 上没有建索引,所以是正常的),耗时 13s 。 但是奇怪的是,如果不用 order by,直接 select * from TableA where TableA.columnA='value'; 花了 1s 不到的时间,因此,可以认为时间都花在了 order by 排序上。 于是他用 select * from TableA order by timestamp; 发现也需要 17s 左右的时间,验证了时间都花在了 order by 上。
现在我的同事灵机一动,想到可以把数据用子查询先查出,再做排序,按道理因为子查询查出的数据量只有 70w,已经降了两个量级了,这个时候再做排序应该要轻松一些。于是: select * from (select * from TableA where Table.A.columnA='value') as B order by B.timestamp; 但是用 explain 一看:
'1','SIMPLE','ulog_data_attitude',NULL,'ALL',NULL,NULL,NULL,NULL, 'xxx','xxx','Using where; Using filesort'
发现用没用子查询执行计划都一样。
现在的问题是: 1. 为什么「先用子查询查出数据,再用 order by 排序子查询的数据」的方法行不通? 2. 这个查询除了对 columnA 建索引外,有没有其他更好的优化方法?
1. 为什么「先用子查询查出数据,再用 order by 排序子查询的数据」的方法行不通? 2. 这个查询除了对 columnA 建索引外,有没有其他更好的优化方法? 答 1. ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。 排序的对象是 where 后的数据,所以你用不用子查询,需要排序的数据都是 70w 。 所以在这里,这个方法是行不通的。
2. 不知道数据插入的时候有 主键是不是按时间戳顺序生成的。如果是那就好办了,直接 order by 主键就行。如果不是,好像除了改业务,或者是加硬件 也就是建立 timestamp 的索引这个方法比较实际了。