3

関連データに対して行う必要がある 2 つのレベルのフィルタリングがあります。最初のクエリは次のようになります。

SELECT t1.fk_id 
FROM t1 
LEFT JOIN t3 ON t3.fk_id = t1.fk_id
WHERE t1.field1 > 10 AND t3.field2 = Y

2 番目のクエリは、同じ fk_id フィールドを持つ別のテーブルに対して実行され、次のようになります。

SELECT t2.fk_id, SUM(t2.field3) AS sum_3, SUM(t2.field_4) AS sum_4 
FROM t2 
WHERE fk_id IN (fk_values_from_query_1)
GROUP BY t2.fk_id
HAVING sum_3 > 1000

さて、私が知る限り、この2つの異なる方法を実行できます-私はどちらの方法にも縛られていませんが、他の方法にも開かれています. 最初のクエリを 2 番目のクエリに SUB-SELECT として埋め込むこともできますが、これはパフォーマンスの観点から非常に悪いと理解しています。または、クエリ 1 の結果から値を抽出し、クエリ 2 (アプリケーション コード) にリストとして埋め込むこともできます。

この質問の 2 つの部分は次のとおりです。

  1. 上記の 2 つのクエリ構造の間にパフォーマンス上の違いはありますか?
  2. これら 2 つのクエリを構造化するより良い方法はありますか?

ベンチマーク

これを完全にテストしたわけではありませんが、私のバージョンと Barmar によって投稿されたバージョンを私のデータに対して実行しました。私のクエリは約 4.23 秒で実行されましたが、Barmar のバージョンは実行に 0.60 秒しかかかりませんでした。これは 85% の改善です。

4

1 に答える 1

3

JOIN を使用してそれらを結合する必要があります。

SELECT t2.fk_id, SUM(t2.field3) AS sum_3, SUM(t2.field_4) AS sum_4 
FROM t2
JOIN (SELECT distinct t1.fk_id
      FROM t1
      JOIN t2 ON t3.fk_id = t1.fk_id
      WHERE t1.field1 > 10 AND t3.field2 = 'Y') t4
ON t2.fk_id = t4.fk_id
GROUP BY t2.fk_id
HAVING sum_3 > 1000

私は一貫して、MySQL がWHERE col IN (subquery)同様の結合と比較して、クエリに対してひどいパフォーマンスを発揮することを発見しました。サブクエリの値を代入するクエリとは比較していません。これは、単一のクエリでは実行できない場合 (たとえば、異なるサーバーのデータを照合する必要がある場合) にのみ実行したためです。

ところで、LEFT JOIN結合されているテーブルの値もフィルタリングしている場合は、 a を使用しても意味がありません。

INいずれの場合も、結合または句で使用されるキーにインデックスがあることを確認してください。

于 2013-05-06T17:32:45.930 に答える