3

私の質問は、プレフィックス マッチングを使用する場合に int COLUMN と組み合わせた VARCHAR の MySQL インデックスの処理に関するものです。たとえば、そのようなクエリがある場合:

SELECT * FROM tbl WHERE name LIKE 'query%' ORDER BY weight DESC LIMIT 5

私が1つのインデックス1つの名前->重みを持っていることを考えると、そのインデックスはプレフィックスのすべての出現を見つけてからqueryORDER BYする必要がありますか、それともプレフィックスマッチング(%)を使用しても相互計算のインデックスを付けたままにしますか. よくある名前 (例: query=john) の場合、john のすべての出現を長時間検索することに気付くかもしれません。これにより、制限が役に立たなくなり、処理中にクエリが遅くなる可能性があります。大規模なデータセットで。

4

2 に答える 2

1

あなたは別の質問「4,000 万の名前によるワイルドカード検索に最適なインデックスの作成」を行いました。4,000 万件のレコードがあります。

ここで、次の式を検討してください。

x = COUNT(DISTINCT values in a column) / COUNT(values in a column)

列のインデックスは、1 に近いほど優れていxます。1 の場合、すべての値が明確であり、重複がないため、インデックスは非常に高速です。

ここで、'john%' を探しています。それは4文字で、オープンエンドです。どの文字が重要ではないか、DB は 26*26*26*26=456976 の異なる値を処理する必要があります。それを上記の式と 4000 万のレコードに入れます。x0,0114244 を取得します。

またしきい値が何かわかりませんが、IIRC は 0,1 か何かです。したがって、x0,1 より大きい場合はインデックスが使用され、それより低い場合は使用されません。

どうしてこんなことに?インデックスを使用すると、処理が遅くなる可能性さえあります。DB がインデックスを確認し、そのインデックスで適切なレコードが物理ハード ドライブのどの位置にあるかを確認し、そのレコードを取得する必要があります。したがって、x が 10% 未満の場合は、テーブル全体をスキャンするだけの方が高速です。

要約すると、あなたのような弱いインデックスが 1 つしかない 4000 万のレコードをフィルタリングしても、まったく役に立ちません。

于 2012-09-06T09:18:42.830 に答える
1

のインデックス付きプレフィックス'query'と同じか短い長さである場合name:

  1. の複合BTREEインデックスは、 then(name, weight)によって並べ替えられます。概念的に:nameweight

    +---------+--------+---------+
    | | 名前(7) | 重量 | 住所 |
    +---------+--------+---------+
    | | クエリ | 500 | 0x1.... |
    | | クエリ | 500 | 0xe.... |
    | | クエリ | 498 | 0x8.... |
    | | クエリ | 491 | 0xb.... |
    | | クエリ | 486 | 0xc.... |
    | | クエリ | 430 | 0x3.... |
    | | クエリアブ | 600 | 0x2.... |
    | | クエリアブ | 592 | 0x7.... |
    | | クエリアブ | 550 | 0x4.... |
    | | クエリアブ | 321 | 0xa.... |
    | | クエリアブ | 321 | 0x6.... |
    | | クエリアブ | 304 | 0x9.... |
    | | クエリアブ | 297 | 0x5.... |
    | | クエリbc | 800 | 0xd.... |
    : : : :
    
  2. MySQL は、そのようなインデックスを非常に迅速に走査して、フィルターによって定義された範囲内の各インデックス付きプレフィックスの上位 5 つの重みを見つけることができますname LIKE 'query%'(このステップを実行するかどうかはわかりませんが、実行しない場合は驚くでしょう)。

    +---------+--------+---------+
    | | 名前(7) | 重量 | 住所 |
    +---------+--------+---------+
    | | クエリ | 500 | 0x1.... |
    | | クエリ | 500 | 0xe.... |
    | | クエリ | 498 | 0x8.... |
    | | クエリ | 491 | 0xb.... |
    | | クエリ | 486 | 0xc.... |
    | | クエリアブ | 600 | 0x2.... |
    | | クエリアブ | 592 | 0x7.... |
    | | クエリアブ | 550 | 0x4.... |
    | | クエリアブ | 321 | 0xa.... |
    | | クエリアブ | 321 | 0x6.... |
    | | クエリbc | 800 | 0xd.... |
    : : : :
    
  3. この時点で、MySQL は結果に対してファイルソートを実行する必要があります。

    +---------+--------+---------+
    | | 名前(7) | 重量 | 住所 |
    +---------+--------+---------+
    | | クエリbc | 800 | 0xd.... |
    | | クエリアブ | 600 | 0x2.... |
    | | クエリアブ | 592 | 0x7.... |
    | | クエリアブ | 550 | 0x4.... |
    | | クエリ | 500 | 0x1.... |
    | | クエリ | 500 | 0xe.... |
    | | クエリ | 498 | 0x8.... |
    | | クエリ | 491 | 0xb.... |
    | | クエリ | 486 | 0xc.... |
    | | クエリアブ | 321 | 0xa.... |
    | | クエリアブ | 321 | 0x6.... |
    : : : :
    
  4. その後、上位 5 つの結果を使用して、関連するレコードをテーブルから取得できます。

    +---------+--------+---------+
    | | 名前(7) | 重量 | 住所 |
    +---------+--------+---------+
    | | クエリbc | 800 | 0xd.... | --> テーブルからフェッチ
    | | クエリアブ | 600 | 0x2.... | --> テーブルからフェッチ
    | | クエリアブ | 592 | 0x7.... | --> テーブルからフェッチ
    | | クエリアブ | 550 | 0x4.... | --> テーブルからフェッチ
    | | クエリ | 500 | 0x1.... | --> テーブルからフェッチ
    +---------+--------+---------+
    

が のインデックス付きプレフィックスより'query'長い場合name、MySQL は上記のステップ 1 でテーブルへのルックアップを実行して、その後に並べられるレコードを適切にフィルタリングする必要があります。

于 2012-09-06T09:21:26.420 に答える