说我有一张表order
为
id | clientid | type | amount | itemid | date
---|----------|------|--------|--------|-----------
23 | 258 | B | 150 | 14 | 2012-04-03
24 | 258 | S | 69 | 14 | 2012-04-03
25 | 301 | S | 10 | 20 | 2012-04-03
26 | 327 | B | 54 | 156 | 2012-04-04
clientid
是返回client
表itemid
是返回item
表type
仅为B
或S
amount
是一个整数和表格processed
为
id | orderid | processed | date
---|---------|-----------|---------
41 | 23 | true | 2012-04-03
42 | 24 | true | 2012-04-03
43 | 25 | false | <NULL>
44 | 26 | true | 2012-04-05
我需要从order
获取同一clientid
个date
上具有相反type
值的所有行。请注意,type
只能包含两个值中的一个 - B
或S
。在上面的示例中,这将是行23
和24
。
另一个限制是,processed
中true
的相应行必须为orderid
。
到目前为止我的查询
SELECT c1.clientid,
c1.date,
c1.type,
c1.itemid,
c1.amount,
c2.date,
c2.type,
c2.itemid,
c2.amount
FROM order c1
INNER JOIN order c2 ON c1.itemid = c2.itemid AND
c1.date = c2.date AND
c1.clientid = c2.clientid AND
c1.type <> c2.type AND
c1.id < c2.id
INNER JOIN processed p1 ON p1.orderid = c1.id AND
p1.processed = true
INNER JOIN processed p2 ON p2.orderid = c2.id AND
p2.processed = true
问题:将processed = true
保留为join子句的一部分会降低查询速度。如果我将它移动到WHERE子句,那么性能会好得多。这激起了我的兴趣, 我想知道为什么 。
主键和相应的外键列都被编入索引,而值列(value
,processed
等)则没有。
免责声明:我继承了这个数据库结构,性能差异大约为6秒。
答案 0 :(得分:9)
您看到差异的原因是由于规划人员正在组合的执行计划,这显然因查询而异(可以说,它应该优化2个查询是相同的,这可能是一个错误)。这意味着规划人员认为必须以特定的方式工作才能在每个陈述中找到结果。
当您在JOIN中执行此操作时,计划程序可能必须从表格中进行选择,按照&#34; True&#34;部分,然后加入结果集。我认为这是一个大表,因此要查看大量数据,并且它不能有效地使用索引。
我怀疑如果你在WHERE子句中这样做,规划者就会选择一种效率更高的路由(即基于索引或预过滤的数据集)。
您可以通过在两列上添加索引来快速(如果不是更快)使连接工作(不确定Postgres是否支持包含的列和多列索引)。
简而言之,规划者就是选择2条不同的路线来达到结果集的问题,其中一条路线不如另一条路线那么高效。如果没有完整的表格信息和EXPLAIN ANALYZE信息,我们无法知道原因是什么。
如果您需要详细说明特定查询的原因,您需要提供更多信息。然而原因是计划者选择不同的路线。
其他阅读材料:
http://www.postgresql.org/docs/current/static/explicit-joins.html
刚刚撇去,似乎postgres规划师没有重新订购连接来优化它。尝试更改语句中连接的顺序,看看你是否获得相同的性能......只是一个想法。