私は日本語の辞書を保存しているデータベースを持っています:単語、読み取り値、タグ、タイプ、他の言語での意味(ここでは英語が最も重要ですが、そうです。MySQLのクエリが遅い場所で
Datatables js pluginを使用してインターフェースを作成したいので、ユーザーはテーブルを見て、いくつかのフィルタリングオプションを使用することができます(動詞だけを表示する、または "dog"を含むエントリを見つける)。しかし、フィルタリングを使用するとかなり遅くなるクエリでは苦労しています...私はすでに多くの速度を上げていますが、それでもまだ良くありません。
これが私の基本的なクエリです:
select
v.id,
(
select group_concat(distinct vke.kanji_element separator '; ') from vocabulary_kanji_element as vke
where vke.vocabulary_id = v.id
) kanji_notation,
(
select group_concat(distinct vre.reading_element separator '; ') from vocabulary_reading_element as vre
where vre.vocabulary_id = v.id
) reading_notation,
(
select group_concat(distinct vsg.gloss separator '; ') from vocabulary_sense_gloss as vsg
join vocabulary_sense as vs on vsg.sense_id = vs.id
join language as l on vsg.language_id = l.id and l.language_code = 'eng'
where vs.vocabulary_id = v.id
) meanings,
(
select group_concat(distinct pos.name_code separator '; ') from vocabulary_sense as vs
join vocabulary_sense_has_pos as vshp on vshp.sense_id = vs.id
join part_of_speech as pos on pos.id = vshp.pos_id
where vs.vocabulary_id = v.id
) pos
from vocabulary as v
join vocabulary_sense as vs on vs.vocabulary_id = v.id
join vocabulary_sense_gloss as vsg on vsg.sense_id = vs.id
join vocabulary_kanji_element as vke on vke.vocabulary_id = v.id
join vocabulary_reading_element as vre on vre.vocabulary_id = v.id
join language as l on l.id = vsg.language_id and l.language_code = 'eng'
join vocabulary_sense_has_pos as vshp on vshp.sense_id = vs.id
join part_of_speech as pos on pos.id = vshp.pos_id
where
-- pos.name_code = 'n' and
(vsg.gloss like '%eat%' OR vke.kanji_element like '%eat%' OR vre.reading_element like '%eat%')
group by v.id
order by v.id desc
-- limit 3900, 25
出力は次のようなものです:今(私のローカルマシン上で作業)、何のWHERE文はありません場合は、しかし制限で
|id | kanji_notation | reading_notation | meanings | pos |
---------------------------------------------------------------
|117312| お手; 御手 | おて | hand; arm |n; int|
、それは速く働きます - 約0,140秒。しかし、テキストフィルタリングが有効になっている場合、実行時間は最大6.5秒になります。最初にpart_of_speechをフィルタリングすると、その5,5秒のようになります。 3秒は大丈夫ですが、6秒は長すぎます。
テーブルvocabulary_sense_glossに1 155 897のレコードがあるので、それほど多くはないと思います。
CREATE TABLE `vocabulary_sense_gloss` (
`id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
`sense_id` MEDIUMINT(8) UNSIGNED NOT NULL,
`gloss` VARCHAR(255) NOT NULL,
`language_id` MEDIUMINT(8) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `vocabulary_sense_gloss_vocabulary_sense_id` (`sense_id`),
INDEX `vocabulary_sense_gloss_language_id` (`language_id`),
FULLTEXT INDEX `vocabulary_sense_gloss_gloss` (`gloss`),
CONSTRAINT `vocabulary_sense_gloss_language_id` FOREIGN KEY (`language_id`) REFERENCES `language` (`id`),
CONSTRAINT `vocabulary_sense_gloss_vocabulary_sense_id` FOREIGN KEY (`sense_id`) REFERENCES `vocabulary_sense` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
私はそれを最適化する方法はありますか?データベースを変更する必要はありますか?私はフルテキスト検索を使用しようとしていましたが、それほど高速ではなく、完全な条件でしか動作しないようです。 '%eat%'の代わりに 'eat%'を使用すると簡単な物語:私が望むものが返されません。
私は、2つのテーブル(英語のみの用語で、もう1つは残りのもの)でvocabulary_sense_glossを分割しようとしました。とにかくユーザーは通常英語を使用するため、作業が速くなりますが、それが良いアプローチであるかどうかはわかりません。
また、私はVARCHARをCHARに変更しようとしていました。テーブルのサイズが大きく増えたにもかかわらず、実行時間を短縮するように見えました。