2

全文索引を追加して基本的なブール検索を行う方法を知っています...

ALTER TABLE products ADD FULLTEXT KEY myIndex (model, description);
SELECT * 
FROM   products 
WHERE  MATCH(model, description) AGAINST('myKeyword' in boolean mode);

しかし、私はこのようなことが可能かどうか疑問に思っています...

SQL で「myIndex」が存在するかどうかを確認し、存在しない場合は、既存の列名を自動的に取得してフルテキスト インデックスを追加する必要があります (列名の代わりに * があることに注意してください)。

ALTER TABLE products ADD FULLTEXT KEY myIndex (*);

また、インデックスを検索するときに、列名を手動で入力する代わりに、列名を再び自動的に取得できますか (列名の代わりに * があることに注意してください)...

SELECT * 
FROM  products 
WHERE MATCH(*) AGAINST('myKeyword' in boolean mode);

正しい構文はわかりませんが、このようなことは可能でしょうか? 私は何時間もグーグルを検索してきましたが、答えを見つけるのに苦労しています。PHP で必要な SQL を生成できることはわかっていますが、厳密に SQL を使用してこれがすべて可能かどうか疑問に思っています。

ありがとう!

4

2 に答える 2

4

コメントに基づいて、データベースを動的にインデックス付けしたいと考えています。これは一般的に良い考えではありません。インデックスは両刃の剣です。説明させてください。

したがって、基本的にインデックスは、インデックスを作成するすべての値を含むディスク上のデータ構造です。たとえば、10 列の 1000 行テーブルがあり、1 列にインデックスを付けると仮定すると、この新しいインデックスにも 1000 エントリが含まれます。その列のすべての行の値が含まれます。このインデックスはディスクに書き込まれるため、読み取ることができます。

次に新しい行を挿入するときは、テーブルとインデックスに挿入する必要があります。インデックス付きの列を更新すると、テーブルとインデックスの両方を更新する必要があります。あなたの質問で私が見ることができることから、いくつかの列に動的にインデックスを付けたいと考えています。

したがって、10 000 000 行と 3 列のかなり大きなテーブルがあり、それらすべてにインデックスを付ける必要がある 30 000 000 の値があるとします。基本的に、このインデックスを動的に作成すると、サーバーはテーブルのインデックス作成中に非常に遅くなります。また、完了すると、挿入が遅くなり、インデックス付きの列への更新が遅くなります。一般的な経験則では、インデックスを使用すると読み取りが速くなり、挿入が遅くなります。

ここで、もう少し複雑にします。MySQL が新しく作成されたインデックスを使用することを保証する方法はありません。MySQL は内部統計を使用して、使用するインデックスを決定します。あなたの場合、全文索引を使用しているため、これはそれほど問題ではないかもしれません。MySQL でインデックスの使用を強制することもできますが、これも最適な方法ではありません。

私が提案できるのであれば、このように最適化しないでください。最適化への非常に一般的なアプローチ、つまりインデックスをどこにでも適用しようとしています。むしろ、スロー クエリ ログを有効にして、実行速度の遅いクエリを特定します。次に、これらのクエリを Explain ステートメントと一緒に使用して、その状況を最適化する方法を特定します。最終的にインデックスが少なくなり、読み書き速度のバランスが良くなります。

これがすべて意味をなすことを願っています。

于 2013-07-17T00:02:46.737 に答える
2

次の方法で全文索引が存在するかどうかを確認できます。

SELECT DISTINCT index_name 
FROM INFORMATION_SCHEMA.STATISTICS
WHERE (table_schema, table_name) = ('mydatabase', 'products')
  AND index_type = 'FULLTEXT';

この方法でそのインデックスの列を取得できます。

SELECT column_name 
FROM INFORMATION_SCHEMA.STATISTICS
WHERE (table_schema, table_name) = ('mydatabase', 'products')
  AND index_type = 'FULLTEXT'
ORDER BY seq_in_index;

使用できませんMATCH(*)。列はスペルアウトする必要があり、インデックス内のすべての列に名前を付ける必要があり、インデックスを定義したときと同じ順序で名前を付ける必要があります。


InnoDB はディスクからランダムなページを読み取ってテーブルとインデックスをサンプリングするため、information_schema に対する一部のクエリが遅く見えることにも注意してください。つまり、メタデータを読み取ると I/O が発生します。でこれを軽減できますSET GLOBAL innodb_stats_on_metadata=0http://www.mysqlperformanceblog.com/2011/12/23/solving-information_schema-slowness/も参照してください。

于 2013-07-16T23:06:49.710 に答える