web-dev-qa-db-ja.com

フルテキストと左結合の遅いクエリ

3つのテーブルがあります

  • 約250,000レコード。
  • table1はMyISAMで、タイトルとコンテンツを含むfullindexを追加し、pidを含むインデックスを追加します。
  • table2とtable3はInnoDBであり、pidを使用してインデックスを追加します。

クエリはtable3のみで、コストは0.04秒です。

select * from table3 
WHERE MATCH (title,content)
AGAINST ('+words' IN BOOLEAN MODE)
ORDER BY pid

このようなクエリは、16.87秒かかります。

SELECT * 
FROM table1
INNER JOIN table2 ON table1.pid = table2.pid
LEFT JOIN table3 ON table1.pid = table3.pid
WHERE MATCH (table3.title, table3.content)
AGAINST ('+words' IN BOOLEAN MODE)
ORDER BY table3.pid

2番目のクエリのEXPLAINプランを作成し、次を返します。

id select_type  table     type  possible_keys    key    key_len    ref               rows      Extra
1  SIMPLE       table1    ALL    pid             NULL   NULL       NULL              201497    Using temporary; Using filesort
1  SIMPLE       table2    ref    pid             pid    32         mydb.table1.pid   1     
1  SIMPLE       table3    ref    pid             pid    32         mydb.table2.pid   222309    Using where
  • 2番目のクエリが遅いのはなぜですか?
  • どうすれば最適化できますか?

ありがとう。

5
cj333

残念ながら、MySQLは期待どおりに動作しています。

問題は、EXPLAINプランのコンパイルでMySQLのクエリオプティマイザーを他のテーブルと組み合わせて使用​​すると非常に混乱するという事実にあります。私は前にこれについて書いた:

私の提案:JOINの前にフルテキスト検索を実行してクエリをリファクタリングしてみてください

SELECT * FROM table1 
INNER JOIN table2 ON table1.pid = table2.pid 
LEFT JOIN
(
    select * from table3  
    WHERE MATCH (title, content) 
    AGAINST ('+words' IN BOOLEAN MODE )
    ORDER BY pid 
) table3
ON table1.pid = table3.pid 
;
5
RolandoMySQLDBA

これは私のヒントです。誰かが何かを追加したい場合、または私が間違っている場合は知らせてください。感謝します。

  • Selectステートメントから*を削除し、必要な列を置くだけです。

    SELECT COLUMN1,COLUMN2,COLUMN3
    FROM table1
    INNER JOIN table2 ON table1.pid = table2.pid
    LEFT JOIN table3 ON table1.pid = table3.pid
    WHERE MATCH (
    table3.title, table3.content
    )
    AGAINST (
    '+words'
    IN BOOLEAN
    MODE
    )
    ORDER BY table3.pid
    
  • すべての結果が必要ない場合は、最後に制限を追加できます。

    ORDER BY table3.pid 
    limit 100;
    
  • 「いいね」を試してみてください(おそらく高速ではありませんが、私は好奇心が強いだけです)。

0
jcho360

おかげで、このメソッドも左結合なしで、0.12秒高速なクエリを取得できます。

SELECT * 
FROM table1,table2,table3
WHERE table1.pid = table2.pid 
and table1.pid = table3.pid 
and MATCH (table3.title, table3.content)
AGAINST ('+words' IN BOOLEAN MODE)
ORDER BY table3.pid
0
cj333