为何Postgres对简单查询选择Parallel Seq Scan而非Index Scan?
Postgres大表查询慢因排查:Parallel Seq Scan替代Index Scan问题
背景
通过INSERT INTO ... SELECT ...语句在同一数据库内迁移了一张超8000万行的表,耗时数小时。迁移后对原表(tmp_migration.asset)和目标表(public.asset)执行相同的主键查询,性能差异极大。此前误以为两张表都在id列设置了主键。
原表(tmp_migration.asset)查询分析
执行的查询语句:
EXPLAIN ANALYZE SELECT * FROM tmp_migration.asset a WHERE id = 1452299
执行计划输出:
"QUERY PLAN" "Gather (cost=1000.00..2723419.51 rows=40149 width=2536) (actual time=56362.052..56411.077 rows=1 loops=1)" " Workers Planned: 2" " Workers Launched: 2" " -> Parallel Seq Scan on asset a (cost=0.00..2718404.61 rows=16729 width=2536) (actual time=53152.645..56349.660 rows=0 loops=3)" " Filter: (id = 1452299)" " Rows Removed by Filter: 26851637" "Planning Time: 0.077 ms" "Execution Time: 56411.114 ms"
注意:简单主键查询耗时近一分钟,Postgres选择了**Parallel Seq Scan(并行全表扫描)**而非索引扫描。
目标表(public.asset)查询分析
执行的查询语句:
EXPLAIN ANALYZE SELECT * FROM public.asset a WHERE id = 107588
执行计划输出:
"QUERY PLAN" "Index Scan using ""PK_1209d107fe21482beaea51b745e"" on asset a (cost=0.57..8.59 rows=1 width=883) (actual time=85.544..85.548 rows=1 loops=1)" " Index Cond: (id = 107588)" "Planning Time: 0.090 ms" "Execution Time: 85.576 ms"
注意:查询执行时间不足100毫秒,Postgres使用了Index Scan(索引扫描)。
已尝试操作
- 检查两张表的主键设置
- 对
tmp_migration.asset执行VACUUM操作
问题原因与解决
经核实,tmp_migration模式下的asset表缺失主键索引——此前通过数据库GUI(Heidi SQL)误判该列为主键,实际并未创建索引。
验证索引状态的查询语句:
SELECT * FROM pg_indexes WHERE schemaname = 'public' OR schemaname = 'tmp_migration'
执行后确认tmp_migration.asset无任何索引。创建主键索引后,查询性能恢复正常:
CREATE INDEX "asset_idx" ON tmp_migration.asset ("id")
内容的提问来源于stack exchange,提问作者bln_dev
相关产品推荐
相关产品推荐

