0

ユーザーが PDF をアップロードしていない特定のモジュール (記事のサブセット) 内の記事をすばやく表示するクエリが必要です。以下で使用しているクエリは、Article テーブルに 300,000 件の記事があり、モジュールに 6,000 件の記事がある場合、約 37 秒かかります。

SELECT * 
FROM article a 
INNER JOIN article_module_map amm ON amm.article=a.id 
WHERE amm.module = 2 AND
    a.id NOT IN ( 
        SELECT afm.article 
        FROM article_file_map afm 
        INNER JOIN article_module_map amm ON amm.article = afm.article 
        WHERE afm.organization = 4 AND 
            amm.module = 2 
    ) 

上記のクエリで行っていることは、最初に記事のリストを選択したモジュールに切り捨て、次にそのリストをサブクエリにない記事に切り詰​​めることです。サブクエリは、組織が既に PDF をアップロードした記事のリストを生成しています。したがって、最終的な結果は、組織がまだ PDF をアップロードしていない記事のリストになります。

事前に感謝します。

編集 2012/10/25

@fthiella の助けを借りて、以下のクエリは驚くべきことに 1.02 秒で実行され、37 秒以上から短縮されました!

SELECT a.* FROM (
    SELECT article.* FROM article 
    INNER JOIN article_module_map
        ON article.id = article_module_map.article
    WHERE article_module_map.module = 2
) AS a
LEFT JOIN article_file_map
    ON a.id = article_file_map.article
    AND article_file_map.organization=4
WHERE article_file_map.id IS NULL
4

2 に答える 2

1

テーブルのロジックと構造を正しく理解できるかどうかわかりません。これは私のクエリです:

SELECT
  article.id
FROM
  article
    INNER JOIN
  article_module_map
    ON article.id = article_module_map.article
    AND article_module_map.module=2
  LEFT JOIN
    article_file_map
    ON article.id = article_file_map.article
    AND article_file_map.organization=4
WHERE
  article_file_map.id IS NULL

モジュール 2 を持つすべての記事を抽出します。次に、組織 4 がファイルを提供しなかった記事を選択します。

サブクエリの代わりに LEFT JOIN を使用しました。状況によっては、これがより速くなる可能性があります。

編集コメントありがとうございます。もっと速く動くかどうかはわかりませんでしたが、とても遅いことに驚きました! とにかくやってみる価値はありました!

さて、好奇心から、LEFT/INNER JOIN とサブクエリのすべての組み合わせを試して、どちらがより速く実行されるかを確認したいと思います。

SELECT *
FROM
  (SELECT *
   FROM
     article INNER JOIN article_module_map
     ON article.id = article_module_map.article
   WHERE
     article_module_map.module=2)
  LEFT JOIN
etc.

* を削除して、WHERE 句の条件と ON 句の条件の間で何が変わるかを確認したいと思います...とにかく、あまり役に立たないと思います。今はインデックスに集中する必要があります。

キー/外部キーのインデックスは既に問題ないはずですが、article_module_map.moduleand/orにインデックスを追加するとどうなりますかarticle_file_map.organization?

于 2012-10-25T09:01:06.273 に答える
1

クエリを最適化するときは、次の点を確認するために使用します。

最初: SELECT 句で * を使用するのは避け、代わりに、必要なさまざまなフィールドに名前を付けます。これにより速度が狂ったように増加します (* で 7 秒かかっていたものがあり、フィールドの名前付けは 0.1 秒に減少しました)。

2番目:@Adderが言うように、テーブルにインデックスを追加します。

3 番目: WHERE amm.module = 2 AND a.id NOT IN ( ... ) の代わりに INNER JOIN を使用してみてください。通常、MySQL は INNER JOINS を最適化し、サブクエリはフィルターであるため、3 つの INNER JOINS と WHERE を使用すると取得が高速になることを読んだと思います (よく覚えていないので、注意深く読んでください)。

于 2012-10-25T08:36:22.913 に答える