2009-08-07 18 views
0

表1からすべての行を一致検索行は:トラックのMySQL - 結合テーブル

表2:ワードリスト

表3:N:Mトラック

は持っているすべてのトラックを検索する単語(trackwords)を有していますすべての言葉。すべてのインデックスを使用しているEXPLAINに従って

SELECT DISTINCT t.id FROM track as t 
Left Join trackwords as tw ON t.id=tw.trackid 
Left Join wordlist as wl on wl.id=tw.wordid 
WHERE 
wl.trackusecount>0 
group by t.id 
HAVING SUM(IF(wl.word IN ('folsom','prison','blues'),1,0)) = 3; 

がneccessary:

+----+-------------+-------+--------+-----------------------+---------+---------+----------------+---------+-------------+ 
| id | select_type | table | type | possible_keys   | key  | key_len | ref   | rows | Extra  | 
+----+-------------+-------+--------+-----------------------+---------+---------+----------------+---------+-------------+ 
| 1 | SIMPLE  | t  | index | PRIMARY    | PRIMARY | 4  | NULL   | 8194507 | Using index | 
| 1 | SIMPLE  | tw | ref | wordid,trackid  | trackid | 4  | mbdb.t.id  |  3 | Using where | 
| 1 | SIMPLE  | wl | eq_ref | PRIMARY,trackusecount | PRIMARY | 4  | mbdb.tw.wordid |  1 | Using where | 
+----+-------------+-------+--------+-----------------------+---------+---------+----------------+---------+-------------+ 

をしかし、クエリは、年齢を取る

は現在、クエリは次のようになります。 クエリを高速化するための提案はありますか?

答えて

3

あなたの問題のセットは、StackOverflowやDel.icio.usのようなアイテムのタグを保存するのと非常によく似ています。

記事Tags: Database schemasは、@ ChssPly76のアイデアの中にいくつかの解決策を提案しています。

+0

非常にいいリンク、本当にありがとう、ありがとう。 – Rufinus

+0

リンクが既に死んでいることを除いて。 –

+0

新しいリンクが見つかりました。 – Rufinus

5

すべての単語を含むトラックのみを検索している場合は、左の結合には意味がありません。私は(trackidwordid)の組み合わせがtrackwordsで一意であると仮定しています。

SELECT t.id 
    FROM track as t, trackwords as tw, wordlist as wl 
WHERE t.id=tw.trackid 
    AND wl.id=tw.wordid 
    AND wl.trackusecount>0 /* not sure what that is - you have it in your query */ 
    AND wl.word in ('folsom','prison','blues') 
GROUP by t.id 
HAVING count(*) = 3 

このクエリは、wordlist(word)、trackwords(trackid、wordid)およびtrack(id)のインデックスから利益を得ます。

+0

あなたの質問は3倍遅くなる誘惑性を使っています。 しかし、あなたのcount()= 3はあなたの持っている良いアイデアです。 SELECT DISTINCT t.name、t.id FROM track from t Leftトラックワードをtwと結合します。ON t.id = tw.trackid Left Join wl.id = tw.wordidの単語リストwl.trackusecount> 0かつwl.word IN( 'folsom'、 'prison'、 'blues')グループby t.id HAVING Count(t.id)= 3 LIMIT 0,10; これは私の本来のクエリより約10倍高速です:) – Rufinus

+0

適切なインデックスが定義されている場合は、テンポラリテーブルを使用すべきではありません。ワードリストで3行、トラックワードでインデックスルックアップ、トラックでインデックスルックアップ – ChssPly76

+0

が奇妙な場合があります。場合によってはバージョンが高速で、場合によっては鉱山が高速です。 (テストする言葉が異なる場合、クエリキャッシュはこの場合強く:-) btw。あなたの解決策はthinkzigからのリンクで言及されているものと同じです。だから私はその権利を推測する:-) – Rufinus

0

これを2つのクエリに分解すると、おそらくもっと速くなります。まず、単語とトラックワードを結合して、必要なすべてのtrackidをネットに入れます。そして、バックトラックテーブルに戻り、操作を行います。

WHERE t.id IN(...trackids here...) 

しかし、あなたが戻っている上記のすべてのクエリに基づいて、あなたはすでにtw.trackidから持ってt.idです。

+0

理論的には正しいですが、私はクエリのSELECT部分​​を分かりやすくするために短くしています:) これを別々のクエリで試してみましたが、すべてのバージョンが低速でした。 – Rufinus