コア2デュオ、8G RAMラップトップで実行されている約400万行の大きなMySQL、MyISAMテーブルがあります。
このテーブルには、varchar、decimal、およびint型を含む30列があります。
varchar(16)にインデックスがあります。この列を「indexed_varchar_column」と呼びましょう。
私の質問は
SELECT 9 columns FROM the_table WHERE indexed_varchar_column = 'something';
クエリを実行する「何か」ごとに、常に約5000行が返されます。
クエリへのEXPLAINはこれを返します:
+----+-------------+-------------+------+----------------------------------------------------+--------------------------------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------+----------------------------------------------------+--------------------------------------------+---------+-------+------+-------------+
| 1 | SIMPLE | the_table | ref | many indexes including indexed_varchar_column | another_index NOT: indexed_varchar_column! | 19 | const | 5247 | Using where |
+----+-------------+-------------+------+----------------------------------------------------+--------------------------------------------+---------+-------+------+-------------+
まず、another_indexが選択された理由がわかりません。実際には、indexed_varchar_columnと別の2つの列(選択された列の一部を形成する)の複合インデックスであるインデックスを選択します。クエリの2つの列を読み取る必要がないため、処理が少し速くなる可能性があるため、おそらくこれは理にかなっています。本当の質問は次のとおりです。
クエリは、一致する「何か」ごとに5秒かかります。2回目に「何か」に対してクエリを実行すると、0.15秒かかります(クエリがキャッシュされているためだと思います)。'something_new'に対して別のクエリを実行すると、再び5秒かかります。だから、それは一貫しています。
問題は次のとおりです。インデックス(indexed_varchar_columnを含む別の複合インデックス)を作成して再度ドロップすると、新しい'something_other'に対する以降のすべてのクエリにかかる時間はわずか0.15秒であることがわかりました。1)インデックスを作成します2)再度ドロップすることに注意してください。したがって、すべてが同じ状態になります。
インデックスの作成と削除に必要なすべての操作により、SQLエンジンが何かをキャッシュして再利用できるようになると思います。この後、クエリでEXPLAINを実行すると、以前とまったく同じになります。
インデックスを操作せずにキャッシュできるように、インデックスの作成と削除の手順で何がキャッシュされているかを理解するにはどうすればよいですか?
アップデート:
mySQLがインデックスを作成するときに内部的にSELECTを実行することを示唆するMarcBからのコメントに続いて、私は次のことを試みました。
SELECT * FROM my_table;
30秒かかり、400万行が返されました。良いことは、それ以降のすべてのクエリが再び非常に高速になることです(システムを再起動するまで)。再起動後、クエリが再び遅くなることに注意してください。これは、mySQLが何らかのOSキャッシングを使用しているためだと思います。
何か案が?推測するテーブルを明示的にキャッシュするにはどうすればよいですか?
更新2: おそらく、このテーブルはひどく断片化されている可能性があることを述べておかなければなりません。400万行ですが、古いフィールドを定期的に削除しています。新しいものも追加します。毎日ID(削除された行)に大きなギャップがあったため、プライマリインデックス(ID)を削除し、連続した番号で再度作成します。その場合、テーブルは非常に断片化される可能性があるため、IOが問題になる可能性があります...どうすればよいかわかりません。