sql >> データベース >  >> RDS >> Mysql

大量のデータでより速く実行できますか[MySQL]

    EXPLAINを見てください 出力では、サブクエリを使用すると、インデックスの使用が最適ではなくなるのではないかと心配していました。 感じた (正当な理由なしに-そしてこれについては私は非常に間違っているかもしれません)JOINを使用して書き直す より最適化されたクエリにつながる可能性があります。

    そのためには、クエリの目的を理解する必要があります。あなたの質問がそれを明確に表現していれば助けになったでしょうが、少し頭を悩ませた後、あなたのクエリは、特定のキーワードを含む記事に表示される他のすべてのキーワードのリストを、カウントとともにフェッチしようとしていると判断しましたそれらのキーワードが表示されるすべての記事の 。

    それでは、クエリを段階的に再構築しましょう:

    1. 特定のキーワードを含む記事」を取得します "(重複について心配する必要はありません):

      SELECT ca2.article_id
      FROM
             career_article_keyword AS ca2
      WHERE
            ca2.keyword_id = 9;
      
    2. "[上記]に表示される他のすべてのキーワードを取得します "

      SELECT ca1.keyword_id
      FROM
             career_article_keyword AS ca1
        JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
      WHERE
            ca1.keyword_id <> 9
        AND ca2.keyword_id =  9
      GROUP BY ca1.keyword_id;
      
    3. [上記]と、それらのキーワードが表示されているすべての記事の数を取得 "

      SELECT ca1.keyword_id, COUNT(DISTINCT ca0.article_id) AS cnt
      FROM
             career_article_keyword AS ca0
        JOIN career_article_keyword AS ca1 USING (keyword_id)
        JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
      WHERE
            ca1.keyword_id <> 9
        AND ca2.keyword_id =  9
      GROUP BY ca1.keyword_id
      ORDER BY cnt DESC;
      
    4. 最後に、career_keywordからの一致するキーワード自体を出力に追加します。 テーブル:

      SELECT ck.keyword_id, ck.keyword, COUNT(DISTINCT ca0.article_id) AS cnt
      FROM
             career_keywords        AS ck 
        JOIN career_article_keyword AS ca0 USING (keyword_id)
        JOIN career_article_keyword AS ca1 USING (keyword_id)
        JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
      WHERE
            ca1.keyword_id <> 9
        AND ca2.keyword_id =  9
      GROUP BY ck.keyword_id -- equal to ca1.keyword_id due to join conditions
      ORDER BY cnt DESC;
      

    すぐにわかることの1つは、元のクエリがcareer_keywordsを参照していることです。 2回ですが、この書き直されたクエリはそのテーブルを1回だけ参照します。これだけでパフォーマンスの違いを説明できるかもしれません-完全に冗長であるため、それへの2番目の参照(つまり、最初のサブクエリで表示される場所)を削除してみてください。

    このクエリを振り返ると、次の列で結合が実行されていることがわかります。

    • career_keywords.keyword_id ck JOIN ca0

      このテーブルは、PRIMARY KEY (`keyword_id`)を定義します 、したがって、この結合に使用できる優れたインデックスがあります。

    • career_article_keyword.article_id ca1 JOIN ca2

      このテーブルは、UNIQUE KEY `article_id` (`article_id`,`keyword_id`)を定義します。 そして、article_id以降 はこのインデックスの左端の列であり、この結合に使用できる適切なインデックスがあります。

    • career_article_keyword.keyword_id ck JOIN ca0で およびca0 JOIN ca1

      この結合に使用できるインデックスはありません。このテーブルで定義されている唯一のインデックスには、別の列article_idがあります。 keyword_idの左側 --MySQLはkeyword_idを見つけることができません article_idを最初に知らなくてもインデックスのエントリ 。 keyword_idを持つ新しいインデックスを作成することをお勧めします 左端の列として。

      (このインデックスの必要性は、2つの最も外側のクエリがその列で結合を実行する元のクエリを調べることからも同様に直接確認できます。)




    1. カウント中、oraclesqlはgroupby式ではありません

    2. 一意のインデックスの違いを説明し、validates_uniqueness_of

    3. SQL Server:CREATEDATABASEでパラメーターを使用する

    4. mysqlはどのようにIPアドレスの逆解決を行いますか?