MySQL Verbietet einen vollen Wert indizieren BLOB
, TEXT
und lange VARCHAR
Spalten , weil Daten , die sie enthalten , können sehr groß sein, und implizit DB - Index wird groß sein, keinen Nutzen aus dem Index bedeutet.
MySQL erfordert, dass Sie die ersten N zu indizierenden Zeichen definieren. Der Trick besteht darin, eine Zahl N zu wählen, die lang genug ist, um eine gute Selektivität zu erzielen, aber kurz genug, um Platz zu sparen. Das Präfix sollte lang genug sein, um den Index fast so nützlich zu machen, wie es wäre, wenn Sie die gesamte Spalte indiziert hätten.
Bevor wir weiter gehen, definieren wir einige wichtige Begriffe. Die Indexselektivität ist das Verhältnis der insgesamt unterschiedlichen indizierten Werte und der Gesamtzahl der Zeilen . Hier ist ein Beispiel für eine Testtabelle:
+-----+-----------+
| id | value |
+-----+-----------+
| 1 | abc |
| 2 | abd |
| 3 | adg |
+-----+-----------+
Wenn wir nur das erste Zeichen indizieren (N = 1), sieht die Indextabelle wie folgt aus:
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| a | 1,2,3 |
+---------------+-----------+
In diesem Fall ist die Indexselektivität gleich IS = 1/3 = 0,33.
Lassen Sie uns nun sehen, was passieren wird, wenn wir die Anzahl der indizierten Zeichen auf zwei erhöhen (N = 2).
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| ab | 1,2 |
| ad | 3 |
+---------------+-----------+
In diesem Szenario ist IS = 2/3 = 0,66, was bedeutet, dass wir die Indexselektivität erhöht haben, aber wir haben auch die Größe des Index erhöht. Der Trick besteht darin, die minimale Zahl N zu finden, die zu maximaler Indexselektivität führt .
Es gibt zwei Ansätze, mit denen Sie Berechnungen für Ihre Datenbanktabelle durchführen können. Ich werde auf diesem Datenbank-Dump demonstrieren .
Lassen Sie uns sagen , dass wir Spalte hinzufügen möchten last_name in der Tabelle Mitarbeiter auf den Index, und wir wollen die kleinste Zahl definieren , N , die die beste Index Selektivität produzieren.
Lassen Sie uns zuerst die häufigsten Nachnamen identifizieren:
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)
Wie Sie sehen können, ist der Nachname Baba der häufigste. Jetzt werden wir die am häufigsten vorkommenden Nachnamen- Präfixe finden, beginnend mit Präfixen aus fünf Buchstaben.
+-----+--------+
| 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)
Es gibt viel mehr Vorkommen von jedem Präfix, was bedeutet, dass wir die Zahl N erhöhen müssen, bis die Werte fast dieselben wie im vorherigen Beispiel sind.
Hier sind die Ergebnisse für 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 |
+-----+-----------+
Hier sind Ergebnisse für 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)
Das sind sehr gute Ergebnisse. Dies bedeutet, dass wir einen Index für eine Spalte last_name
erstellen können, wobei nur die ersten 10 Zeichen indiziert werden. In der Tabellendefinition last_name
ist die Spalte definiert als VARCHAR(16)
, und dies bedeutet, dass wir 6 Bytes (oder mehr, wenn der Nachname UTF8-Zeichen enthält) pro Eintrag gespeichert haben. In dieser Tabelle gibt es 1637 verschiedene Werte multipliziert mit 6 Bytes, was ungefähr 9 KB entspricht. Stellen Sie sich vor, wie diese Zahl wachsen würde, wenn unsere Tabelle Millionen von Zeilen enthält.
Sie können andere Methoden zur Berechnung der Anzahl von N in meinen Post- Präfix-Indizes in MySQL lesen .
UNIQUE
Schlüssel hat?