我正在构建一个使用两个不同SQL查询的应用程序。我在同一个Postgres表上对这两个查询运行EXPLAIN ANALYZE
以了解它们的性能。
查询1:Xmin查询
explain analyze
select * from table where xmin::text::bigint >= xmin_max_value;
输出:
Seq Scan on users (cost=0.00..91302235.56 rows=666658645 width=141) (actual time=1686004.249..1686004.250 rows=0 loops=1)
Filter: (((xmin)::text)::bigint >= xmin_max_value)
Rows Removed by Filter: 2000000000
Planning Time: 3.066 ms
Execution Time: 1686004.308 ms
查询2:未索引字段查询
explain analyze
select * from "2b_users".users where age > max_age;
结果:
Gather (cost=1000.00..56720318.43 rows=1 width=141) (actual time=545081.498..545083.143 rows=0 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on users (cost=0.00..56719318.33 rows=1 width=141) (actual time=545071.505..545071.505 rows=0 loops=3)
Filter: (age > 100)
Rows Removed by Filter: 666666667
Planning Time: 0.153 ms
Execution Time: 545083.178 ms`
我对这些查询进行了设置,使每个查询都不返回任何数据。这是因为我在每种情况下选择的游标值代表与该字段关联的最大游标值。
我对这种行为有几个问题:
- Postgres查询规划器如何确定是否执行并行顺序扫描?我本来希望这两个查询有相同的计划,因为它们都是未索引的字段。
- 我知道
xmin
是一个系统列。系统级的列是否会阻止查询计划器执行并行扫描?文档中没有任何内容可以解释为什么这应该是顺序扫描:https://www.postgresql.org/docs/current/parallel-plans.html - 是否有方法/设置打开
xmin
查询的并行扫描?并行扫描要快得多,所以理想情况下,我希望这个查询也能利用并行扫描。
1条答案
按热度按时间vd8tlhqk1#
这个差异是由PostgreSQL的估计造成的。第一个查询估计返回666658645行,而第二个查询估计返回一行。在并行worker之间交换行是昂贵的,并且每个元组的代价为0.1(参数
parallel_tuple_cost
)。这使得一个平行计划在这种情况下失败。令人费解的原因是PostgreSQL不知道
xmin::text::bigint
是如何分发的,你对此无能为力。如果要强制计划者手动,请将parallel_tuple_cost
设置为0以执行查询。顺便说一下,你的查询似乎是错误的。看起来您正在尝试查找新添加的行,但这在此查询中不会可靠地工作,因为事务ID会循环。