2011-02-09 8 views
1

私はMySQLを使用して、それがこのようなクエリを実行するために多くの時間を要し、いくつかの理由のためだ:このSQLクエリを最適化する方法は? (映画データベース)

SELECT 
    DISTINCT (Movies.id) AS id, 
    Movies.UnMoID AS UnMoID, 
    Movies.runtime AS runtime 
FROM 
    Movies 
INNER JOIN Acted ON Acted.UnMoID = Movies.UnMoID 
INNER JOIN Actors ON Acted.UnMoActorID = Actors.UnMoActorID 
INNER JOIN Directed ON Directed.UnMoID = Movies.UnMoID 
INNER JOIN Directors ON Directed.UnMoDirectorID = Directors.UnMoDirectorID 
WHERE 
    Actors.name LIKE '%spiderman%' 
    OR Directors.name LIKE '%spiderman%' 
    OR Movies.originalTitle LIKE '%spiderman%' 
    OR Movies.englishTitle LIKE '%spiderman%' 
    OR Movies.alsoKnownAs LIKE '%spiderman%' 
    OR Movies.taglines LIKE '%spiderman%' 
    OR Movies.plot LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20 
GROUP BY Movies.id 
ORDER BY added DESC 

これは私を与えるだろう:「(6.5320秒でクエリを実行され、2の結果を得ました")

この特定のクエリに対する説明

ができます:

id select_type table  type possible_keys   key   key_len ref       rows Extra 
1 SIMPLE  Movies ALL UnMoID     NULL   NULL  NULL       925 Using temporary; Using filesort 
1 SIMPLE  Directed ref UnMoID,UnMoDirectorID UnMoID   62  Movies.Movies.UnMoID    1  
1 SIMPLE  Directors eq_ref UnMoDirectorID   UnMoDirectorID 62  Movies.Directed.UnMoDirectorID 1  
1 SIMPLE  Acted  ref UnMoID,UnMoActorID  UnMoID   62  Movies.Movies.UnMoID   34 
1 SIMPLE  Actors eq_ref UnMoActorID   UnMoActorID 62  Movies.Acted.UnMoActorID   1 Using where 

プロファイリング情報:

...... 
Creating tmp table 0.000032 
Sorting for group  0.000007 
executing    0.000005 
Copying to tmp table 6.324177 
Sorting result  0.000027 
Sending data   0.000019 
...... 

それはクエリと時間のほとんどは、に行くたびに実行するために20秒程度かかり、最悪のケースではCopying to tmp table。クエリを最適化し、適切なクエリ時間を得るためにはどうすればよいですか。

Movies.id     PRIMARY 
Movies.UnMoID    UNIQUE 
Movies.runtime   INDEX 
Acted.UnMoID    INDEX 
Acted.UnMoActorID   INDEX 
Actors.UnMoActorID  UNIQUE 
Actors.name    UINDEX 
Directed.UnMoID   INDEX 
Directed.UnMoDirectorID INDEX 
Directors.UnMoDirectorID UNIQUE 
Directors.name   INDEX 
Movies.originalTitle  INDEX 
Movies.englishTitle  INDEX 
Movies.alsoKnownAs  INDEX 
Movies.taglines   INDEX 
Movies.plot    INDEX 
+0

「DISTINCT」に続く大きな結合の方が遅くなります。重複がないように結合を書き直してください。 – OrangeDog

答えて

0

私はあなたの状態がとても広いので遅さの理由があると思います。代わりに、私は単純なクエリを作って試してみても、重複を取り除くでしょうUNION、とそれらを組み合わせると思います。

それぞれ個のクエリは非常に高速であり、存在しないと仮定しているので、このようなものが有益かもしれません(私はあなたのDBを持っていないので、

(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies INNER JOIN Actors ON Acted.UnMoActorID = Actors.UnMoActorID 
WHERE Actors.name LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
UNION 
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies INNER JOIN Directed ON Directed.UnMoID = Movies.UnMoID 
INNER JOIN Directors ON Directed.UnMoDirectorID = Directors.UnMoDirectorID 
WHERE Directors.name LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
UNION 
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies 
WHERE Movies.originalTitle LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
UNION 
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies 
WHERE Movies.englishTitle LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
UNION 
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies 
WHERE Movies.alsoKnownAs LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
UNION 
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies 
WHERE Movies.taglines LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
UNION 
(SELECT Movies.id, Movies.UnMoID, Movies.runtime, added 
FROM Movies 
WHERE Movies.plot LIKE '%spiderman%' 
    AND Movies.validated =1 
    AND Movies.ageCertificate <=20) 
ORDER BY added DESC 

並べ替えまたはフィルタリングするフィールドをクエリ結果に含める必要があります。

サブセレクトをサポートするエンジンを使用している場合は、検証と年齢認証のフィルタ条件を個々のクエリから一般的なラッパークエリに移すことができます。このため、メリットは主に繰り返しの削除になります。メンテナンス:

SELECT id, UnMoID, runtime FROM 
(SELECT ...) Q -- the above query including all necessary fields 
WHERE Movies.validated =1 
AND Movies.ageCertificate <=20 
ORDER BY added DESC 
+0

これは試してみる価値があるようです。以前の提案では、クエリ時間を5秒に短縮できましたが、それでも時間がかかります。私は家に帰るとすぐにこれを試してみる...仕事の7と時間だけ残って...;) – Damiqib

+1

最後にこれをテストした。私はこれで2.2秒のクエリ時間を得ることができました。私のために十分に良い。ありがとうございました。 – Damiqib

2

インデックスがリードするワイルドカードとLIKE検索を助けにはなりません。

は私がのためにインデックスを持っています。あなたはfull-text searchの実装を検討することをお勧めします。検索のような

+0

はできるだけ早く私が家に帰ると、私はこれに見ていきます。ありがとうございました。 – Damiqib

+0

おっと。これはMyISAMテーブルでのみ動作するようですが、InnoDBを使用しています。この場合の解決策はありますか? – Damiqib

1

MYSQLは本当に遅く、全文検索機能では、MyISAMテーブルでのみ利用可能です。最適化されたインデックスを持つ読み取りスレーブを使用して試したり、最適化したりできますが、それほど多くは得られません。

私はSPHINXまたはSOLR(data importer for MYSQL)のような検索エンジンを使用してクエリを移動します。

関連する問題