MySQLでは、プレフィックス付きインデックスを定義できます。つまり、インデックスを作成する元の文字列の最初のN文字を定義します。トリックは、選択性を高めるのに十分ですが、スペースを節約するのに十分短いNを選択することです。プレフィックスは、列全体にインデックスを付ける場合と同じくらいインデックスを有用にするのに十分な長さでなければなりません。
先に進む前に、いくつかの重要な用語を定義しましょう。インデックスの選択性は、合計の個別のインデックス値と合計行数の比率です。テストテーブルの例を次に示します。
+-----+-----------+
| id | value |
+-----+-----------+
| 1 | abc |
| 2 | abd |
| 3 | adg |
+-----+-----------+
最初の文字(N = 1)のみをインデックス付けすると、インデックステーブルは次の表のようになります。
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| a | 1,2,3 |
+---------------+-----------+
この場合、インデックスの選択性はIS = 1/3 = 0.33に等しくなります。
インデックス文字の数を2に増やした場合(N = 2)に何が起こるか見てみましょう。
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| ab | 1,2 |
| ad | 3 |
+---------------+-----------+
このシナリオでは、IS = 2/3 = 0.66です。これは、インデックスの選択性を高めたことを意味しますが、インデックスのサイズも増やしました。トリックは、最大のインデックス選択性をもたらす最小数Nを見つけることです。
データベーステーブルの計算を実行できる方法は2つあります。このデータベースダンプのデモンストレーションを行います。
テーブルemployeesのlast_name列をインデックスに追加し、最適なインデックス選択性が得られる最小数Nを定義するとします。
まず、最も頻繁に使用される姓を特定します。
select count(*) as cnt, last_name from employees group by employees.last_name order by cnt
+-----+-------------+
| cnt | last_name |
+-----+-------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Farris |
| 222 | Sudbeck |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Neiman |
| 218 | Mandell |
| 218 | Masada |
| 217 | Boudaillier |
| 217 | Wendorf |
| 216 | Pettis |
| 216 | Solares |
| 216 | Mahnke |
+-----+-------------+
15 rows in set (0.64 sec)
ご覧のように、姓のババが最もよく使用されます。次に、5文字のプレフィックスで始まる、最も頻繁に発生するlast_nameプレフィックスを見つけます。
+-----+--------+
| cnt | prefix |
+-----+--------+
| 794 | Schaa |
| 758 | Mande |
| 711 | Schwa |
| 562 | Angel |
| 561 | Gecse |
| 555 | Delgr |
| 550 | Berna |
| 547 | Peter |
| 543 | Cappe |
| 539 | Stran |
| 534 | Canna |
| 485 | Georg |
| 417 | Neima |
| 398 | Petti |
| 398 | Duclo |
+-----+--------+
15 rows in set (0.55 sec)
すべての接頭辞の出現回数がはるかに多いため、値が前の例とほぼ同じになるまで数値Nを増やす必要があります。
N = 9の結果は次のとおりです
select count(*) as cnt, left(last_name,9) as prefix from employees group by prefix order by cnt desc limit 0,15;
+-----+-----------+
| cnt | prefix |
+-----+-----------+
| 336 | Schwartzb |
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudailli |
| 216 | Cummings |
| 216 | Pettis |
+-----+-----------+
N = 10の結果は次のとおりです。
+-----+------------+
| cnt | prefix |
+-----+------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudaillie |
| 216 | Cummings |
| 216 | Pettis |
| 216 | Solares |
+-----+------------+
15 rows in set (0.56 sec)
これは非常に良い結果です。つまり、最初の10文字のみをインデックス付けして、last_name列にインデックスを作成できます。テーブル定義列のlast_nameはとして定義されてVARCHAR(16)
おり、これはエントリごとに6バイト(または姓にUTF8文字がある場合はそれ以上)を保存したことを意味します。このテーブルには、1637個の異なる値に6バイトを掛けたものが約9KBあり、テーブルに数百万行が含まれる場合にこの数がどのように増加するかを想像してください。
あなたは多くの計算の他の方法読み取ることができるNを私のポストにMySQLでの同一キーのインデックスを。
インデックスを作成する必要がある値を生成するためにMD5およびSHA1関数を使用することも、適切なアプローチではありません。どうして?ポストで読むMySQLデータベースの主キーに適切なデータ型を選択する方法