3

以下のようなクエリがあったとしましょう..

SELECT 
    name,category,address,city,state
FROM
    table
WHERE 
    MATCH(name,subcategory,category,tag1) AGAINST('education')
AND 
    city='Oakland'
AND
    state='CA' 
LIMIT
    0, 10;

..そして、私はfulltextインデックスとしてname,subcategory,category,tag1compositeインデックスとしてを持っていましたcity,state; このクエリにはこれで十分ですか?ANDフルテキスト インデックスを MATCH/AGAINST で使用するときに追加の を混合するときに、何か特別なものが必要かどうか疑問に思っています。

編集:私が理解しようとしているのは、クエリ内にあるが、選択したインデックス (フルテキスト インデックス) でインデックスが作成されていない追加の列で何が起こるかです。上記の例はcityandstateです。MySQL は 2 つのインデックスを使用できないため (または使用できますか?)、これらに一致するをどのように見つけますか?フルテキスト インデックスと、クエリを最適化するためにできること、またはすべきことがある場合。

4

3 に答える 3

7

あなたの質問が理解できれば、MATCH AGAINST が FULLTEXT インデックスを使用し、MySQL が残りの WHERE 句をどのように適用するのか (つまり、テーブルスキャンまたはインデックス付きルックアップを行うのか) を知りたいと思います。

あなたのテーブルについて私が想定していることは次のとおりです。いくつかの id 列に PRIMARY KEY と FULLTEXT インデックスがあります。

最初に、MySQL は都市/州の WHERE 句に FULLTEXT インデックスを使用しません。なんで?FULLTEXT インデックスは MATCH AGAINST でのみ適用されるためです。箇条書きの最初のセットの後の段落のhereを参照してください(目次の箇条書きではありません)。

編集:あなたの場合、テーブルに10行ほどしかないと仮定すると、MySQLはMATCH AGAINSTにFULLTEXTインデックスを適用し、それらの結果に対してtablescanを実行して都市/州のWHEREを適用します。

では、都市と州に BTREE インデックスを追加するとどうなるでしょうか。

CREATE INDEX city__state ON table (city(10),state(2)) USING BTREE;

これは単純な選択であるため、MySQL はこのクエリに1 つのインデックスしか使用できません。FULLTEXTまたはBTREEを使用します。1 つのインデックスと言うときは、マルチパート インデックスの 1 つの列ではなく、1 つのインデックス定義を意味することに注意してください。Anwway、これは次に、どちらを使用するのかという疑問を投げかけます。

それはテーブル分析に依存します。MySQL は、(最後の OPTIMIZE TABLE からのテーブル統計に基づいて) どのインデックスが最も多くのレコードを削除するかを推定しようとします。市/州の WHERE ではレコードが 10 まで減り、MATCH AGAINST では 100 までしか減らない場合、MySQL は市/州の WHERE に対して最初にcity__state インデックスを使用し、次に MATCH AGAINST に対して tablescan を実行します。

一方、MATCH_AGAINST によってレコードが 10 に減少し、都市/州の WHERE によって 1000 に減少した場合、MySQL は最初に FULLTEXT インデックスを適用し、都市と州のテーブルスキャンを適用します。

肝心なのは、インデックスのカーディナリティです。基本的に、インデックスに追加される値はどの程度固有のものですか? テーブル内のすべてのレコードの city が Oakland に設定されている場合、それはあまり一意のキーではないため、city = 'Oakland'を指定してもレコード数はそれほど減りません。その場合、city__state インデックスのカーディナリティが低いと言います。

したがって、FULLTEXT インデックスの単語の 90% が「John」である場合、まったく同じ理由であまり役に立ちません。

スペースと UPDATE/DELETE/INSERT のオーバーヘッドに余裕がある場合は、BTREE インデックスを追加し、使用するインデックスを MySQL に決定させることをお勧めします。私の経験では、彼は通常、正しいものを選ぶという非常に良い仕事をしています.

それがあなたの質問に答えることを願っています。

編集:補足として、BTREE インデックスに適切なサイズを選択していることを確認してください (私の例では、city の最初の 10 文字を選択しました)。これは明らかにカーディナリティに大きな影響を与えます。city(1) を選択した場合、明らかに、city(10) を選択した場合よりもカーディナリティが低くなります。

EDIT2:インデックスが最も多くのレコードをプルーニングする MySQL のクエリ プラン (推定) は、EXPLAIN に表示されるものです。

于 2012-09-21T03:37:02.333 に答える
1

しばらく前に同様のタスクを実行しましたが、MySQLは1つのクエリでFULLTEXTインデックスまたはその他のインデックスのいずれかを使用できますが、両方を使用することはできません。FULLTEXTを他のインデックスと混在させることができませんでした。全文検索による選択は、次のように機能します。

  • 全文検索を使用してサブセットを選択します
  • そのサブセットから他の基準に一致するレコードを選択します'Usingwhere'

したがって、フルテキストインデックスまたはその他のインデックスのいずれかを使用できます(FORCE INDEXまたはその他の方法で両方のインデックスを使用することはできませんでした)。

フルテキストと他のインデックス(つまり、City列とState列)の両方を使用してみて、結果を比較することをお勧めします。データベースの実際のコンテンツによって異なる場合があります。

私の場合、そのようなクエリで通常の(非フルテキスト)インデックスを強制すると、パフォーマンスが向上することを発見しました(行数が非常に多く、約300 000であり、非フルテキスト基準がそれらの約1000に一致したため)。

MySQL5.5.24を使用していました

于 2012-09-20T08:27:18.933 に答える
1

クエリで使用することで、どのインデックスが使用されるかを簡単に判断できると思いEXPLAINます。の出力を解釈する方法に関するいくつかの優れたリソースを提供する、この質問に対する受け入れられた回答を確認してくださいEXPLAIN

2 つのインデックスを使用できないため、MySQL はこれらに一致する行をどのように見つけるのですか?

はい、できます。MySQL は単一のクエリに対して複数のインデックスを使用できますか? また、ドキュメントを読む必要があります: How MySQL Uses Indexes

于 2012-09-17T22:41:49.717 に答える