【发布时间】:2011-10-30 19:36:32
【问题描述】:
我有两个功能相同的查询。其中一个表现非常好,另一个表现很差。我看不出性能差异是从哪里产生的。
查询 #1:
SELECT id
FROM subsource_position
WHERE
id NOT IN (SELECT position_id FROM subsource)
这会带来以下计划:
QUERY PLAN
-------------------------------------------------------------------------------
Seq Scan on subsource_position (cost=0.00..362486535.10 rows=128524 width=4)
Filter: (NOT (SubPlan 1))
SubPlan 1
-> Materialize (cost=0.00..2566.50 rows=101500 width=4)
-> Seq Scan on subsource (cost=0.00..1662.00 rows=101500 width=4)
查询 #2:
SELECT id FROM subsource_position
EXCEPT
SELECT position_id FROM subsource;
计划:
QUERY PLAN
-------------------------------------------------------------------------------------------------
SetOp Except (cost=24760.35..25668.66 rows=95997 width=4)
-> Sort (cost=24760.35..25214.50 rows=181663 width=4)
Sort Key: "*SELECT* 1".id
-> Append (cost=0.00..6406.26 rows=181663 width=4)
-> Subquery Scan on "*SELECT* 1" (cost=0.00..4146.94 rows=95997 width=4)
-> Seq Scan on subsource_position (cost=0.00..3186.97 rows=95997 width=4)
-> Subquery Scan on "*SELECT* 2" (cost=0.00..2259.32 rows=85666 width=4)
-> Seq Scan on subsource (cost=0.00..1402.66 rows=85666 width=4)
(8 rows)
我有一种感觉,要么我的某个查询遗漏了一些明显不好的地方,要么我错误地配置了 PostgreSQL 服务器。我本来希望这个NOT IN 能很好地优化; NOT IN 总是性能问题还是有原因没有在这里优化?
补充资料:
=> select count(*) from subsource;
count
-------
85158
(1 row)
=> select count(*) from subsource_position;
count
-------
93261
(1 row)
编辑:我现在已经修复了下面提到的 A-B != B-A 问题。但是我所说的问题仍然存在:查询#1仍然比查询#2差很多。我相信这是因为两个表的行数相似。
编辑 2:我正在使用 PostgresQL 9.0.4。我不能使用 EXPLAIN ANALYZE,因为查询 #1 花费的时间太长。所有这些列都不是 NULL,因此应该没有区别。
编辑 3:我对这两列都有索引。我还没有完成查询#1(大约 10 分钟后放弃)。查询 #2 立即返回。
【问题讨论】:
-
@mu 太短:这正是问题所在。不同的查询语义。你应该这样回答
-
我已经更正了;请再看看。
-
您需要指定您使用的 PostgreSQL 版本。另外,我现在也不相信这些查询是相同的 - 考虑 NULL 值。最后,您应该始终发布 EXPLAIN ANALYZE 而不仅仅是简单的 EXPLAIN。
-
NOT IN 就性能而言通常是个坏主意。这可能是 PostgreSQL 拥有(可能是专有的,因为我在其他 RDBMS 中从未听说过它)除了。您没有说查询实际上是否需要不同的时间来执行,或者它是否只是估计的成本(这可能是相当低的)。那么索引呢?
-
@Marian 仅供参考,MS SQL Server 和 IBM DB2 有 EXCEPT,Oracle 有 MINUS。我猜其他数据库也有它们的等价物......
标签: sql postgresql