lightdb中 rownum 作为约束条件时,使用"COUNT STOPKEY" 查询优化技术,原理是在扫描表时,会在满足rownum < N 条件的记录数量达到指定值后停止扫描,而不是继续扫描整个表。这样可以节省大量的IO 和处理时间。
当前rownum 不支持并行的"COUNT STOPKEY" ,对于一些的场景,查询效率会很低。比如下面的SQL ,test 是一张大表,过滤条件需要满足b < 10 and rownum < 100; 如果 b < 10 的记录位于很多不同的数据块中,这时候就需要顺序扫描很多的数据块,直到满足 rownum < 100 才会停止。如果只是使用一个进程去扫描这样的表可能就没有多个进程去扫描的效率高了,所以,我们需要有一个可以并行执行的计划。
explain (costs off)
select rownum, a from test
where b < 10 and rownum < 100;
QUERY PLAN
--------------------------
Count StopKey
-> Seq Scan on test
Filter: (b < 10)
(3 rows)
并行”COUNT STOPKEY” 的思路如下:
l 每个 work 进程做如下的工作: 扫描一部分数据,然后将满足约束条件的数据返回给上层的”PARALLEL COUNT STOPKEY” ,在满足 rownum < N 条件的记录数量达到指定值后停止扫描。
l Leader 进程做如下工作: 收集每个 work 进程返回的 N 条数据( Leader 进程也做了 work 进程的一部分工作),然后将将这些数据再返回给上层的 ”COUNT STOPKEY” ,该 ”COUNT STOPKEY” 还会再进行一次过滤,最终返回 N 条数据。
效果
-- 默认走了并行,执行时间 568.314 ms explain analyze select rownum, a from test where b < 10 and rownum < 100; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------ Count StopKey (cost=1000.00..9455.15 rows=99 width=12) (actual time=0.284..568.213 rows=4 loops=1) -> Gather (cost=1000.00..34820.60 rows=396 width=12) (actual time=0.283..568.210 rows=4 loops=1) Workers Planned: 4 Workers Launched: 4 -> Parallel Count StopKey (cost=0.00..33781.00 rows=99 width=12) (actual time=442.731..555.289 rows=1 loops=5) -> Parallel Seq Scan on test (cost=0.00..85305.55 rows=250 width=12) (actual time=442.726..555.282 rows=1 loops=5) Filter: (b < 10) Rows Removed by Filter: 1999999 Planning Time: 0.139 ms Execution Time: 568.314 ms (10 rows) -- 强制走非并行,执行用时 1618.765 ms SET min_parallel_table_scan_size = 99999; explain analyze select rownum, a from test where b < 10 and rownum < 100; QUERY PLAN ---------------------------------------------------------------------------------------------------------------- Count StopKey (cost=0.00..17726.66 rows=99 width=12) (actual time=0.016..1618.701 rows=4 loops=1) -> Seq Scan on test (cost=0.00..179057.19 rows=1000 width=12) (actual time=0.015..1618.699 rows=4 loops=1) Filter: (b < 10) Rows Removed by Filter: 9999996 Planning Time: 0.189 ms Execution Time: 1618.765 ms (6 rows)