38

说我有一张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具有相反的值。请记住,只能有两个值之一 -或。在上面的示例中,这将是 rows和。clientiddatetypetypeBS2324

另一个约束是 in 中的对应行processed必须trueorderid.

到目前为止我的查询

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 = trueas 作为连接子句的一部分会减慢查询速度。如果我将其移至 WHERE 子句,则性能会好得多。这激起了我的兴趣,我想知道为什么

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

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

4

1 回答 1

19

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

当您在 JOIN 中执行此操作时,规划器可能必须从表中进行选择,按“True”部分过滤,然后加入结果集。我想这是一个大表,因此需要查看大量数据,并且它不能有效地使用索引。

我怀疑如果您在 WHERE 子句中执行此操作,则规划器正在选择更有效的路线(即基于索引或预过滤数据集)。

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

简而言之,规划器的问题在于它选择 2 条不同的路线来获得结果集,其中一条路线的效率不如另一条路线。如果没有完整的表信息和 EXPLAIN ANALYZE 信息,我们是不可能知道原因的。

如果您想详细了解您的特定查询为何这样做,则需要提供更多信息。然而,原因是规划者选择了不同的路线。

附加阅读材料:

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

刚刚略读,似乎 postgres 计划程序不会重新排序连接以优化它。尝试更改语句中连接的顺序,看看您是否获得相同的性能......只是一个想法。

于 2012-06-01T12:25:24.643 回答