ファイルパスを保存したいテーブルがあるので、サイズ4096(LinuxのデフォルトのMAX_PATHサイズ)のvarcharフィールドがあります。ただし、特定のディレクトリ内のすべてのファイルパスのクエリを実行できる必要があるため、次のようなクエリを実行することを考えていました。
SELECT *
FROM files_table
WHERE files_table.path LIKE "/my/awesome/dir/%"
パスフィールドをUNINDEXEDにしてデータベースでこれを実行すると、約10秒かかります。テーブルのサイズが約400万で、インデックス付けされていないフィールドであることを考えると、しばらく時間がかかることがわかります。ただし、インデックスサイズを500にしてインデックスを作成すると、クエリ時間が急増します...最大で約30秒になります。
これは私には非常に混乱しているようです。何がこれを引き起こしているのかについて誰かが何か考えを持っていますか?
より多くのデータに飢えている人のために:
少し余分なデータとして-クエリで「explain」を実行してみたところ、実際にインデックスを使用していることがわかりましたが、key_lenは5つしか報告されていません。これも奇妙に思えます。
また、私の質問に対する良い答えを聞きたいのですが(ここで何が起こっているのかを理解したいので!)、「なぜそれが行われているのかわかりませんが、そうではありません。重要なのは、データベースをこのように設計する必要があるからです...」そのように傾倒している人のために、私が本当にやろうとしているのは、大規模なネットワークファイルシステムからのさまざまな(キャッシュされた)データのクエリを実行するデータベース構造を構築することです。ファイルパスを保存するだけがおそらくこれにアプローチする最も素朴な方法であることを私は知っていますが、私はそれをファーストパス実装として試してみて、それがどこに到達したかを確認すると思いました。
編集:
したがって、もう少し掘り下げ/情報:実際のインデックスは複数列のインデックスです-最初のインデックスはintであり、batch_idを保持します(つまり、テーブルはファイルシステムに関するキャッシュされた情報を保持するため、各スナップショットは独自のbatch_idを取得します)、 2つ目は、パスvarcharの部分インデックスです。したがって、EXPLAINがインデックスkey_lenを言うとき、その最初の4バイトは実際にはbatch_id用です。つまり、パスのインデックスは1バイトしかないということです。
ああ、「実際の」クエリはbatch_idにも制限があるので、次のようになります。
SELECT *
FROM files_table
WHERE batch_id=5
AND files_table.path LIKE "_globalSoft/my/awesome/dir/%"
次に、データベース内のファイルの大部分が「_」で始まるパスを持っています-上記のクエリの「_globalSoft」はその一例です。(はい、パスはすべて相対的です。)したがって、key_lenが5しかない場合、キーで使用されている唯一の文字が先頭の「_」である可能性があります。これは、なぜこれほど遅いのかを説明します。
もちろん、これでも、なぜ先頭の「_」のみを使用しているのかという疑問が生じます。MySQLインデックスのドキュメント(http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html)を読んでいると、次の行に気づきました。
文字列は自動的にプレフィックスとエンドスペースで圧縮されます。13.1.8項「CREATEINDEX構文」を参照してください。
残念ながら、与えられたリンクは文字列プレフィックス圧縮について何も述べておらず、私はそれについて多くの情報を見つけるのに苦労しています。私が見つけた情報はすべてMyISAMに関するものであり、現在InnoDBを使用しています。(ただし、MyISAMに切り替えるのは理にかなっているかもしれませんが、文字列の方が優れていると思われます。)