优化LIMIT分页/优化UNION查询

1,384 阅读2分钟

优化LIMIT分页/优化UNION查询

优化limit分页

在偏移量非常大的时候,例如可能是LIMIT 10000,20这样的查询,这是Mysql需要查询10020条记录然后只返回最后20条,前面10000条记录都将抛弃,这样的代价非常的高。

优化此类分页查询的一个最简单的办法就是尽可能地使用索引覆盖扫描,而不是查询所有的列。然后根据需要做一次关联操作再返回所需要的类。对于偏移量很大的时候这样的效率会提升非常大。考虑下面的查询:

select film_id,description from sakila.film order by tigle  limit 50,5

如果这个表非常大,最好改写成:

select  film.film_id, file.description from sakila. sakila.film inner join (select film_id form sakila.film order by title limit 50,5) as lim using(film_id)

这里的“延迟关联”将大大提升效率,它让MySQL扫描尽可能少的页面,获取所需要的记录后再根据关联列回原表查询需要的所有列。

LIMIT 和 OFFSET的问题,其实是OFFSET的问题,它会导致Mysql扫描大量不需要的行然后抛弃掉。如果可以使用书签记录上次取数据的位置,那么下次就可以直接从该书签记录的位置开始扫描,这样就可以避免使用OFFSET。比如:首先使用下面的查询获取第一组的结果

select * from sakila.rental order by rental_id desc limit 20

假如上面的查询返回的主键为16049到16030,那么下一页查询就可以直接从

16030这个点开始:

select * from sakila.rental where rental_id < 16030 order by 
rental_id desc limit 20

优化union查询:

除非确实需要服务器消除重复的行,否则一定要使用union all,这一点很重要。如果没有all 关键字,mysql会给临时表加上distinct选项,这回导致对这个临时表的数据做唯一性检查。这样的代价非常高

Ref:

《高性能Mysql》 P242