前提・実現したいこと
フルテキストインデックスでの検索において、ORDER BY
を早めたいです。
発生している問題
下記のCREATE
に対するSELECT
において、ORDER BY
があると約10秒、ないと0.1秒となります。
該当のソースコード
テスト用レコードでmy_contents
には100万件ほどが、my_tag_relations
には1000万件ほどがINSERT
されています。
SQL
1CREATE TABLE IF NOT EXISTS my_contents ( 2 ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT 3 ,sentences_ID BIGINT(20) UNSIGNED NOT NULL 4 ,is_official TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 5 ,lang_id INT(3) UNSIGNED NOT NULL DEFAULT 0 6 ,count_likes INT(10) UNSIGNED NOT NULL DEFAULT 0 7 8 ,PRIMARY KEY (ID) 9 ,INDEX idx_my_contents_01 (is_official, lang_id, count_likes) 10 ,INDEX idx_my_contents_02 (sentences_ID) 11 ,INDEX idx_my_contents_03 (count_likes, ID) 12); 13 14CREATE TABLE IF NOT EXISTS my_sentences ( 15 ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT 16 ,sentence VARCHAR(500) CHARACTER SET utf8mb4 NOT NULL 17 18 ,PRIMARY KEY (ID) 19 ,UNIQUE u_my_sentences_01 (sentence) 20 ,FULLTEXT full_my_sentences_01 (sentence) WITH PARSER ngram 21); 22 23CREATE TABLE IF NOT EXISTS my_tags ( 24 ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT 25 ,tag_kind_id INT(3) UNSIGNED NOT NULL DEFAULT 1 26 ,tag_name VARCHAR(500) NOT NULL 27 ,lang_id INT(3) UNSIGNED NOT NULL DEFAULT 0 28 ,is_official TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 29 30 ,PRIMARY KEY (ID) 31 ,INDEX u_my_tags_01 (tag_kind_id, tag_name) 32 ,INDEX idx_my_tags_01 (is_official, tag_kind_id, lang_id) 33 ,INDEX idx_my_tags_02 (tag_name) 34); 35 36CREATE TABLE IF NOT EXISTS my_tag_relations ( 37 tags_ID BIGINT(20) UNSIGNED NOT NULL 38 ,contents_ID BIGINT(20) UNSIGNED NOT NULL 39 40 ,PRIMARY KEY (tags_ID, contents_ID) 41 ,INDEX idx_my_tag_relations_01 (contents_ID) 42 ,CONSTRAINT fk_my_tag_relations_01 FOREIGN KEY (tags_ID) REFERENCES my_tags(ID) 43 ,CONSTRAINT fk_my_tag_relations_02 FOREIGN KEY (contents_ID) REFERENCES my_contents(ID) 44);
上記に対し次のSELECT
をしましたが、10秒ほどかかってしまいます。
SQL
1SELECT contents.ID 2 3FROM my_contents contents 4 LEFT JOIN my_sentences sentences 5 ON sentences.ID = contents.sentences_ID 6 LEFT JOIN my_tag_relations tr 7 ON tr.contents_ID = contents.ID 8 LEFT JOIN my_tags tags 9 ON tags.ID = tr.tags_ID 10 11-- 結果は「100 total, Query took 9.2875 seconds. 」と10秒ほどかかってしまいます 12WHERE MATCH (sentences.sentence) AGAINST ('あいうえお' IN BOOLEAN MODE) OR 13 tags.tag_name = 'あいうえお' 14 15GROUP BY contents.ID 16ORDER BY contents.count_likes DESC, contents.ID DESC 17LIMIT 0, 100
試したこと
遅い原因を突き止めるべく上記SELECT
でEXPLAIN
を出しましたが、type
にAll
があるわけでもなく、これでいいように見えます。
続いてORDER BY
を削除した次のSELECT
では0.1秒ほどになりました。
SQL
1-- 結果は「100 total, Query took 0.1099 seconds.」と0.1秒ほどになりました。 2WHERE MATCH (sentences.sentence) AGAINST ('あいうえお' IN BOOLEAN MODE) OR 3 tags.tag_name = 'あいうえお' 4 5GROUP BY contents.ID 6# ORDER BY contents.count_likes DESC, contents.ID DESC 7LIMIT 0, 100
しかしORDER BY
を削除したくはありませんので、残したままで取得を早める方法を探しています。
良い方法ございましたら宜しくお願い致します。
補足情報(FW/ツールのバージョンなど)
MySQLは 5.7 系を使用しています。
回答1件
あなたの回答
tips
プレビュー