実際の経験を持つ人なら誰でも、フィールドにプレーンなINDEXがある場合、速度と効率の観点から、LIKEクエリはMySQLで数百万行のテーブルに対してどのように実行されますか?
あまりよくありません(私は900kの範囲でいくつかの検索を行ったと思いますが、数百万行のLIKEの経験があるとは言えません)。
通常、検索はできる限り制限する必要がありますが、これはテーブルの構造とアプリケーションのユースケースによって異なります。
また、一部のWebユースケースでは、個別のキーワードにインデックスを付け、キーワードテーブルとrows_contains_keyword(id_keyword、id_row)テーブルを作成するなど、いくつかのトリックを使用してパフォーマンスとユーザーエクスペリエンスを実際に向上させることができます。キーワードテーブルはAJAXで使用され、検索語(単純な単語)を提案し、それらを整数(id_keywords)にコンパイルします。その時点で、それらのキーワードを含む行を見つけるのは非常に速くなります。一度に1行ずつテーブルを更新することも、非常にパフォーマンスが高くなります。もちろん、バッチ更新は明確な「禁止」になります。
これは、+演算子のみを使用する場合、フルテキストMATCH..INBOOLEANMODEですでに実行されていることとそれほど変わりません。
SELECT * FROM arts WHERE MATCH (title) AGAINST ('+MySQL +RDBMS' IN BOOLEAN MODE);
おそらく、InnoDBテーブルでそれを実行する必要があります。
ブール全文検索には、次の特徴があります。
- 関連性の高い順に行を自動的に並べ替えることはありません。..。
- InnoDBテーブルでは、ブールクエリを実行するためにMATCH()式のすべての列にFULLTEXTインデックスが必要です。MyISAM検索インデックスに対するブールクエリは、FULLTEXTインデックスがなくても機能しますが、この方法で実行される検索は非常に遅くなります。..。
- MyISAM検索インデックスに適用される50%のしきい値は使用しません。
特定のケースについて詳しく教えてください。
更新:AJAXの方法
セットアップ:すべてtitle
のsを単語に分割します。title_words
これはすぐにあなたにテーブル( id integer not null autoincrement, word varchar(50) )
と大きなテーブルを与えるでしょうtitle_contains_word ( word_id integer, title_id integer )
。
1000万のタイトルがあり、平均4語(本の場合は妥当ですが、論文の場合はそれほどではありません)の場合、5000行title_words
のテーブルと2つのINTEGER列を含む4000万のテーブルが期待できます。これは約400MBの追加データです。
検索の場合、ユーザーは単語の入力を開始します。これは、タイトル単語からオートコンプリートできます。これが行われると、クエリは単語IDのリストになります。もちろん、タイトルに含まれていない単語も入力できないため、否定的な結果がすぐに無料で表示されます。
実際の検索はいくつかの方法で実行できるようになりましたが、私が気に入っている検索はSELECT COUNT(*) FROM title_contains_word WHERE word_id={id}
、各ユーザーが選択した後、実際の検索が開始される前に実行されます。
これにより、最もまれな単語から開始して、複合クエリまたは共通テーブル式を作成できます。実際、単語の数が20未満の場合、(平均して)8つのTCW行をすべて選択し、関連するすべての単語のIDを取得してから、(MySQLの外部で)そのようなタイトルIDがあることを確認するだけです。クエリのすべてのwordIDにペア(titleID、wordID)が存在すること。
可能な限りラフな形に頼らなければならない場合でも、
SELECT a.title_id
FROM title_contains_word AS tcw1
JOIN title_contains_word AS tcw2 USING (title_id)
JOIN title_contains_word AS tcw3 USING (title_id)
JOIN title_contains_word AS tcw4 USING (title_id)
...
WHERE (tcw1.word_id = {id1})
AND (tcw2.word_id = {id2})
...
JOINは、スキャンにほとんど時間がかからない非常に小さな仮想バッファテーブルから作成されます。
関連するすべてのタイトルIDを取得したら、主キーtitle_idを使用して、数百万行の大規模DBからストレートSELECTを実行できます。この最後の検索も非常に高速であるはずです。