性能差异:INNER JOIN与WHERE子句的条件

时间:2012-06-01 10:56:42

标签: sql performance postgresql query-optimization

说我有一张表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仅为BS
  • 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获取同一clientiddate上具有相反type值的所有行。请注意,type只能包含两个值中的一个 - BS。在上面的示例中,这将是行2324

另一个限制是,processedtrue的相应行必须为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子句,那么性能会好得多。这激起了我的兴趣, 我想知道为什么

主键和相应的外键列都被编入索引,而值列(valueprocessed等)则没有。

免责声明:我继承了这个数据库结构,性能差异大约为6秒。

1 个答案:

答案 0 :(得分:9)

您看到差异的原因是由于规划人员正在组合的执行计划,这显然因查询而异(可以说,它应该优化2个查询是相同的,这可能是一个错误)。这意味着规划人员认为必须以特定的方式工作才能在每个陈述中找到结果。

当您在JOIN中执行此操作时,计划程序可能必须从表格中进行选择,按照&#34; True&#34;部分,然后加入结果集。我认为这是一个大表,因此要查看大量数据,并且它不能有效地使用索引。

我怀疑如果你在WHERE子句中这样做,规划者就会选择一种效率更高的路由(即基于索引或预过滤的数据集)。

您可以通过在两列上添加索引来快速(如果不是更快)使连接工作(不确定Postgres是否支持包含的列和多列索引)。

简而言之,规划者就是选择2条不同的路线来达到结果集的问题,其中一条路线不如另一条路线那么高效。如果没有完整的表格信息和EXPLAIN ANALYZE信息,我们无法知道原因是什么。

如果您需要详细说明特定查询的原因,您需要提供更多信息。然而原因是计划者选择不同的路线。

其他阅读材料:

http://www.postgresql.org/docs/current/static/explicit-joins.html

刚刚撇去,似乎postgres规划师没有重新订购连接来优化它。尝试更改语句中连接的顺序,看看你是否获得相同的性能......只是一个想法。