为何带OFFSET的SELECT查询成本随OFFSET增大递增?期望恒定成本
问题:为何OFFSET递增会导致查询成本线性上升?
已知id是data表的主键,执行以下EXPLAIN查询后得到的成本如下:
EXPLAIN SELECT id FROM data LIMIT 1000000,查询成本为0.44..18840.00;EXPLAIN SELECT id FROM data LIMIT 1000000 OFFSET 1000000,查询成本为18840.00..37679.56;EXPLAIN SELECT id FROM data LIMIT 1000000 OFFSET 2000000,查询成本为37679.56..56519.12;EXPLAIN SELECT id FROM data LIMIT 1000000 OFFSET 3000000,查询成本为56519.12..75358.69;
可见查询成本随OFFSET增大线性递增,若跳过1000万条数据获取100万条数据,耗时长达数小时。期望该类查询成本维持在0.44或18840左右,想知道为何实际成本会随OFFSET递增?
原因分析
- OFFSET的底层处理逻辑:数据库遇到
OFFSET N时,不会直接跳转到第N+1条数据,而是必须从头开始遍历前N条记录,把这些数据全部跳过之后,才会去读取后面的LIMIT指定条数。哪怕id是主键,这个跳过的过程也没法省略——数据库得一条一条数到目标位置,跳过的数据越多,花费的IO和CPU资源就越多,查询成本自然跟着涨。 - 主键索引的遍历特性:就算id是聚簇主键索引,数据库处理OFFSET时还是得沿着索引树一步步往前挪。比如
OFFSET 1000000,就需要从索引的最开头出发,遍历100万条索引记录才能找到起始位置,这100万次遍历的开销都会被算进查询成本里,所以OFFSET越大,累计成本就越高。 - 成本估算的规则:EXPLAIN里的成本值是数据库根据表的统计信息算出来的,每跳过一条数据都会加上对应的读取成本。你看每次OFFSET加100万,成本就增加差不多18840,这就是跳过100万条数据的总开销,所以整体呈现线性递增的趋势。
内容的提问来源于stack exchange,提问作者bashism
相关产品推荐
相关产品推荐

