【发布时间】:2012-06-06 14:49:40
【问题描述】:
假设我有一张桌子order as
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 作为连接子句的一部分会减慢查询速度。如果我将其移至 WHERE 子句,则性能会好得多。这激起了我的兴趣,我想知道原因。
主键和相应的外键列被索引,而值列(value、processed 等)不被索引。
免责声明:我继承了这个DB结构,性能差异大约是6秒。
【问题讨论】:
-
你能显示两个语句的执行计划(最好使用
explain analyze)吗?但这听起来确实像一个错误。您可能希望将执行计划上传到explain.depesz.com,而不是内联发布。 -
用
c1.type = 'b' and c2.type = 's'替换c1.type <> c2.type会改善一切吗? -
@TokenMacGuy 从语义上讲,这会不会有所不同,即只有当和's'出现在'b'之后? c1.id
-
您可能会看到它们是等价的,但数据库不太可能知道它们只能以一种顺序出现。
-
@Insectatorious:回答@Token 的问题:不,但
(c1.type = 'b' and c2.type = 's') OR (c1.type = 's' and c2.type = 'b')可能比c1.type <> c2.type快。
标签: sql performance postgresql query-optimization