0

PHP で書かれた古いフォーラム ソフトウェアの検索機能をすばやく最適化しようとしています。私は次のようなクエリに自分の仕事をまとめました:

SELECT thread.threadid
FROM thread AS thread
INNER JOIN word AS word ON (word.title LIKE 'word1' OR word.title LIKE 'word2')
INNER JOIN postindex AS postindex ON (postindex.wordid = word.wordid)
INNER JOIN post AS postquery ON (postquery.postid = postindex.postid)
WHERE thread.threadid = postquery.threadid
GROUP BY thread.threadid
HAVING COUNT(DISTINCT word.wordid) = 2
LIMIT 25;

word1word2は例です。言葉はいくつあってもいい。クエリの最後の数字は単語の総数です。アイデアは、スレッドには検索クエリ内のほとんどすべての単語が含まれており、任意の数の投稿に分散しているということです。

このクエリは、たった 2 語で 60 秒を超えることが多く、タイムアウトします。私は困惑しています。この恐ろしい検索エンジンをさらに最適化する方法がわかりません。

私が知る限り、すべてが適切にインデックス化されており、ANALYZE最近実行しました。データベースのほとんどは InnoDB で実行されています。の出力は次のEXPLAINとおりです。

+----+-------------+-----------+--------+----------------------------------------------------------------------------------------+---------+---------+------------------------------+------+-----------------------------------------------------------+
| id | select_type | table     | type   | possible_keys                                                                          | key     | key_len | ref                          | rows | Extra                                                     |
+----+-------------+-----------+--------+----------------------------------------------------------------------------------------+---------+---------+------------------------------+------+-----------------------------------------------------------+
|  1 | SIMPLE      | word      | range  | PRIMARY,title                                                                          | title   | 150     | NULL                         |    2 | Using where; Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | postindex | ref    | wordid,temp_ix                                                                         | temp_ix | 4       | database1.word.wordid        |    3 | Using index condition                                     |
|  1 | SIMPLE      | postquery | eq_ref | PRIMARY,threadid,showthread                                                            | PRIMARY | 4       | database1.postindex.postid   |    1 | NULL                                                      |
|  1 | SIMPLE      | thread    | eq_ref | PRIMARY,forumid,postuserid,pollid,title,lastpost,dateline,prefixid,tweeted,firstpostid | PRIMARY | 4       | database1.postquery.threadid |    1 | Using index                                               |
+----+-------------+-----------+--------+----------------------------------------------------------------------------------------+---------+---------+------------------------------+------+-----------------------------------------------------------+

アップデート

LIMIT 25あまり役に立っていないようです。通常は何百もの結果を返すクエリよりも、おそらく数秒短縮されます。

明確化

MySQL を遅くしている部分はGROUP BY ... HAVING ...ビットです。ではGROUP BYLIMITパフォーマンスの向上にはほとんど役に立ちません。がなくGROUP BYても、残っている限りLIMIT、クエリは非常に高速です。

SQL 情報

の出力SHOW CREATE TABLE postindex;:

CREATE TABLE `postindex` (
  `wordid` int(10) unsigned NOT NULL DEFAULT '0',
  `postid` int(10) unsigned NOT NULL DEFAULT '0',
  `intitle` smallint(5) unsigned NOT NULL DEFAULT '0',
  `score` smallint(5) unsigned NOT NULL DEFAULT '0',
  UNIQUE KEY `wordid` (`wordid`,`postid`),
  KEY `temp_ix` (`wordid`),
  KEY `postid` (`postid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

私はテーブルを作成していないので、wordid に重複したインデックスがある理由がわかりません。ただし、これは古くて気まぐれなソフトウェアであるため、削除するつもりはありません。

4

2 に答える 2

0

まず、一時テーブルを作成し、検索に一致する個別 (thread.threadid、word.wordid) を保存します。次に、count() = 検索された単語の数である thread.threadid を選択します。

于 2013-09-03T13:14:12.560 に答える