2016-04-12 14 views
0

多くの中で、特定のSQLクエリのために、アプリケーションの1ページが非常にゆっくりと読み込まれることがわかりました。多くの行を返すSELECTサブクエリを使用したSELECT IN()SQLクエリの最適化

私はthis document about subquery optimizationを読みましたが、MySQLがどのようにサブクエリを最適化するかを概説していて、どのようにクエリを最適化できるかは概説されていませんでした。私はドキュメントから得たアイデアを試してみましたが、役に立たなかったのです。

これは現在、私の遅いクエリです。私は読みやすくするために、テーブル名とカラム名を簡素化:

SELECT 
    a.one, a.two, a.three, a.four, 
    b.*, 
    a.id, 
    b.id, 
    c.one, c.id, 
    d.one, 
    f.one 
FROM a 
JOIN b ON a.id = b.a_id 
JOIN c ON c.id = b.c_id 
JOIN e ON b.e_id = e.id 
JOIN d ON d.id = e.d_id 
JOIN f ON f.id = b.f_id 
WHERE a.id IN (
    SELECT a_id FROM b WHERE a_id IS NOT NULL AND g_id = 95 
) 

SELECTサブクエリは、現在、私は親クエリの遅延が発生すると思わ750+行を返します。クエリ全体には25秒かかります。

このクエリはどのように最適化できますか?

+0

どのテーブルが 'g_id'ですか? –

答えて

0

5.6.5より前では、MySQLはサブクエリを実現しませんでした。これは、結合の各レコードについて、次の相関クエリを実行することを意味します。

SELECT 1 
FROM b 
WHERE a_id IS NOT NULL 
     AND g_id = 95 
     /* optimizer added */ 
     AND a_id = a.id 
LIMIT 1 

さらにオプティマイザによって条件が追加されます。

5.6.5より、MySQLはINサブクエリの結果を一時テーブルにマテリアライズし、それを他のものと結合することができます。

あなたが前に5.6.5へのMySQLを使用している場合は、参加して、あなたの条件を書き換えてみてくださいすることができます

SELECT a.one, a.two, a.three, a.four, 
     b.*, 
     a.id, 
     b.id, 
     c.one, c.id, 
     d.one, 
     f.one 
FROM (
     SELECT DISTINCT a_id 
     FROM b 
     WHERE a_id IS NOT NULL 
       AND g_id = 95 
     ) bi 
JOIN a ON a.id = bi.a_id 
JOIN b ON a.id = b.a_id 
JOIN c ON c.id = b.c_id 
JOIN e ON b.e_id = e.id 
JOIN d ON d.id = e.d_id 
JOIN f ON f.id = b.f_id 

そしてもちろんインデックスのを、関連するすべてのフィールドを適切に。

+0

最後にこれを追加することで、私はあなたの提案を得ました: 'WHERE b.g_id = 95'、つまり外側のクエリをフィルタリングする必要がありました – Obay

+0

好奇心不足のため、MySQLではWHERE EXISTS()あまりにも? – deroby

+0

@deroby:それはそうです – Quassnoi

関連する問題