【发布时间】:2022-01-22 02:31:39
【问题描述】:
我在查询中使用了 2 个表:tableA 和 tableB。 TableA 的行数为 80568353,tableB 的行数为 101806780。它们都共享相同的 10 列(tableB 有额外的 4 列),包括 p_id。我的目标是有一个查询,它从 tableA 创建一个新表,其中 p_id 与 tableB 中的 p_id 不匹配。这是我的查询:
CREATE TABLE my_schema.tableC AS
SELECT * FROM my_schema.tableA
WHERE p_id NOT IN (SELECT DISTINCT p_id::int FROM my_schema.tableB)
这通宵运行,从未完成。我跑去EXPLAIN 看看为什么。结果如下:
Gather (cost=20252382.21..3330358576969.77 rows=40283932 width=89)
Workers Planned: 7
-> Parallel Seq Scan on tableA (cost=20251382.21..3330354547576.57 rows=5754847 width=89)
Filter: (NOT (SubPlan 1))
SubPlan 1
-> Materialize (cost=20251382.21..20814813.52 rows=6107669 width=8)
-> Unique (cost=20251382.21..20760416.17 rows=6107669 width=8)
-> Sort (cost=20251382.21..20505899.19 rows=101806792 width=8)
Sort Key: tableB.p_id
-> Seq Scan on tableB (cost=0.00..5079937.92 rows=101806792 width=8)
我是 PostgreSQL 新手,但 cost=20251382.21..3330354547576.57 似乎非常高。我尝试返回并运行以下命令来创建索引以加快速度:
CREATE INDEX IF NOT EXISTS a_p_int_idx ON my_schema.tableA (CAST(p_id as int));
CREATE INDEX IF NOT EXISTS b_p_int_idx ON my_schema.tableB (CAST(p_id as int));
这似乎没有帮助。我还在两张桌子上运行了VACUUM ANALYZE。没有得到改善。我在这里做错了什么;有什么方法可以提高速度并让它运行或实现我的目标的替代方法?注意:tableA 的 p_id 是 int,tableB 的 p_id 是双精度。会不会有影响?
更新:我无法让 EXPLAIN ANALYZE 完成,但我能够运行 EXPLAIN VERBOSE
Gather (cost=20506959.93..3330368701110.81 rows=40283932 width=89)
Output: tableA.geoid, tableA.p_id, tableA.land_use_t, tableA.prop_ind_t, tableA.story_nbr, tableA.bld_units, tableA.censuspop, tableA.hu_pop, tableA.point_x, tableA.point_y
Workers Planned: 7
-> Parallel Seq Scan on my_schema.tableA (cost=20505959.93..3330364671717.61 rows=5754847 width=89)
Output: tableA.geoid, tableAs.p_id, tableA.land_use_t, tableA.prop_ind_t, tableA.story_nbr, tableA.bld_units, tableA.censuspop, tableA.hu_pop, tableA.point_x, tableA.point_y
Filter: (NOT (SubPlan 1))
SubPlan 1
-> Materialize (cost=20505959.93..21069392.95 rows=6107669 width=4)
Output: ((tableB.p_id)::integer)
-> Unique (cost=20505959.93..21014995.61 rows=6107669 width=4)
Output: ((tableB.p_id)::integer)
-> Sort (cost=20505959.93..20760477.77 rows=101807136 width=4)
Output: ((tableB.p_id)::integer)
Sort Key: ((tableB.p_id)::integer)
-> Seq Scan on my_schema.tableB (cost=0.00..5334459.20 rows=101807136 width=4)
Output: (tableB.p_id)::integer
我也试过
EXPLAIN VERBOSE
SELECT * FROM my_schema.tableA a
WHERE NOT EXISTS(SELECT p_id FROM
my_schema.tableB
WHERE p_id::int = a.p_id)
测试NOT EXISTS 的建议,但成本相同(没有真正的改进)。
【问题讨论】:
-
你能告诉我们 EXPLAIN(ANALYZE, VERBOSE, BUFFERS) 的结果吗?没有它,就不可能看到时间都花在了哪里。
-
不需要子查询中的
distinct。 -
注意:tableA 的 p_id 是 int,tableB 的 p_id 是双精度。那会影响它吗? (添加到问题中)
-
顺便说一下,NOT EXISTS() 很可能比您现在使用的 NOT IN() 构造更快。
-
如果您在两个表的选择中有相同的列,您可以尝试使用 EXCEPT 子句,例如: CREATE TABLE my_schema.tableC AS SELECT p_id FROM my_schema.tableA EXCEPT SELECT DISTINCT p_id::int FROM my_schema .tableB
标签: sql postgresql performance indexing