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
as
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
の2つの値のいずれかしか指定できないことに注意してください。上記の例では、これはrows 23
および24
。
もう1つの制約は、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秒です。
違いが見られる理由は、プランナーがまとめている実行計画によるもので、これは明らかにクエリによって異なります(おそらく、2つのクエリが同じになるように最適化する必要があり、これはバグかもしれません) )。これは、計画者が各ステートメントの結果に到達するために特定の方法で作業する必要があると考えることを意味します。
JOIN内でそれを行う場合、プランナーはおそらくテーブルから選択し、「True」部分でフィルタリングし、結果セットを結合する必要があります。これは大きなテーブルであり、したがって多くのデータを調べる必要があるため、インデックスを効率的に使用することはできません。
WHERE句でそれを行う場合、プランナーはより効率的なルート(つまり、インデックスベースのデータセットまたは事前にフィルタリングされたデータセット)を選択していると思われます。
おそらく、2つの列にインデックスを追加することにより、結合を高速に(高速ではない場合)動作させることができます(Postgresで含まれている列と複数の列インデックスがまだサポートされているかどうかはわかりません)。
要するに、プランナーは結果セットに到達するために2つの異なるルートを選択する問題であり、それらの1つは他のルートほど効率的ではありません。完全なテーブル情報とEXPLAIN ANALYZE情報がなければ、その理由を知ることは不可能です。
特定のクエリがこれを行っている理由の詳細が必要な場合は、詳細情報を提供する必要があります。ただし、その理由は、プランナーが異なるルートを選択しているためです。
追加資料:
http://www.postgresql.org/docs/current/static/explicit-joins.html
スキムしただけで、postgresプランナーは最適化のために結合の順序を変更しないようです。ステートメントの結合の順序を変更して、同じパフォーマンスが得られるかどうかを確認してみてください。