sql >> Database >  >> RDS >> MariaDB

Een gids voor MySQL-indexen

Wanneer MySQL-queryoptimalisatie wordt genoemd, zijn indexen een van de eerste dingen die aan bod komen. Vandaag zullen we proberen te zien waarom ze zo belangrijk zijn.

Wat zijn indexen?

Over het algemeen is een index een alfabetische lijst van records met verwijzingen naar de pagina's waarop ze worden vermeld. In MySQL is een index een gegevensstructuur die wordt gebruikt om snel rijen te vinden. Indexen worden ook sleutels genoemd en die sleutels zijn van cruciaal belang voor goede prestaties - naarmate de gegevens groter worden, kan de noodzaak om indexen correct te gebruiken steeds belangrijker worden. Het gebruik van indexen is een van de krachtigste manieren om de prestaties van zoekopdrachten te verbeteren. Als indexen correct worden gebruikt, kunnen de prestaties van de zoekopdracht tientallen of zelfs honderden keren toenemen.

Vandaag zullen we proberen de basis voor- en nadelen van het gebruik van indexen in MySQL uit te leggen. Houd er rekening mee dat alleen MySQL-indexen een heel boek verdienen, dus dit bericht zal niet absoluut alles behandelen, maar het zal een goed startpunt zijn. Voor degenen die geïnteresseerd zijn in hoe indexen op een dieper niveau werken, zou het lezen van het boek Relational Database Index Design and the Optimizers van Tapio Lahdenmäki en Michael Leach meer inzicht moeten geven.

De voordelen van het gebruik van indexen

Er zijn een paar belangrijke voordelen van het gebruik van indexen in MySQL en deze zijn als volgt:

  • Indexen kunnen snel rijen vinden die overeenkomen met een WHERE-clausule;
  • Indexen kunnen ervoor zorgen dat zoekopdrachten niet door bepaalde rijen hoeven te worden gezocht, waardoor de hoeveelheid gegevens die de server moet onderzoeken, wordt verminderd - als er een keuze is tussen meerdere indexen, gebruikt MySQL meestal de meest selectieve index, dat wil zeggen index die het kleinste aantal rijen vindt;
  • Indexen kunnen worden gebruikt om rijen uit andere tabellen op te halen in JOIN-bewerkingen;
  • Indexen kunnen worden gebruikt om de minimum- of maximumwaarde te vinden van een specifieke kolom die een index gebruikt;
  • Indexen kunnen worden gebruikt om een ​​tabel te sorteren of te groeperen als de bewerkingen worden uitgevoerd op een meest linkse prefix van een index - op dezelfde manier kan een meest linkse prefix van een index met meerdere kolommen ook worden gebruikt door de query-optimizer om rijen op te zoeken;
  • Indexen kunnen ook worden gebruikt om schijf-I/O op te slaan - wanneer een dekkende index in gebruik is, kan een query waarden rechtstreeks uit de indexstructuur retourneren om schijf-I/O op te slaan.

Evenzo zijn er meerdere typen indexen:

  • INDEX is een type index waarbij waarden niet uniek hoeven te zijn. Dit type index accepteert NULL-waarden;
  • UNIEKE INDEX wordt vaak gebruikt om dubbele rijen uit een tabel te verwijderen - met dit type index kunnen ontwikkelaars de uniciteit van rijwaarden afdwingen;
  • FULLTEXT INDEX is een index die wordt toegepast op velden die gebruikmaken van zoekmogelijkheden in volledige tekst. Dit type index vindt trefwoorden in de tekst in plaats van waarden rechtstreeks te vergelijken met de waarden in de index;
  • DESCENDING INDEX is een index die rijen in aflopende volgorde opslaat - de query-optimizer kiest dit type index wanneer een aflopende volgorde wordt gevraagd door de query. Dit indextype is geïntroduceerd in MySQL 8.0;
  • PRIMAIRE SLEUTEL is ook een index. In een notendop, de PRIMARY KEY is een kolom of een reeks kolommen die elke rij in een tabel identificeert - vaak gebruikt in combinatie met velden met een AUTO_INCREMENT-attribuut. Dit type index accepteert geen NULL-waarden en eenmaal ingesteld, kunnen de waarden in de PRIMARY KEY niet worden gewijzigd.

Nu zullen we proberen om zowel de voordelen als de nadelen van het gebruik van indexen in MySQL door te nemen. We beginnen met het waarschijnlijk meest besproken voordeel:het versnellen van zoekopdrachten die overeenkomen met een WHERE-clausule.

Query's versnellen die overeenkomen met een WHERE-clausule

Indexen worden vaak gebruikt om zoekopdrachten die overeenkomen met een WHERE-clausule te versnellen. De reden waarom een ​​index dergelijke zoekbewerkingen sneller maakt, is vrij eenvoudig:zoekopdrachten die een index gebruiken, vermijden een volledige tabelscan.

Om query's die overeenkomen met een WHERE-clausule te versnellen, kunt u gebruik maken van het EXPLAIN-statement in MySQL. De instructie EXPLAIN SELECT zou u enig inzicht moeten geven over hoe de MySQL-query-optimizer de query uitvoert - het kan u ook laten zien of de query in kwestie een index gebruikt of niet en welke index deze gebruikt. Bekijk de volgende vraaguitleg:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: NULL

key: NULL

key_len: NULL

<...>

De bovenstaande zoekopdracht gebruikt geen index. Als we echter een index toevoegen aan "field_1", zou de index met succes worden gebruikt:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: field_1

key: field_1

key_len: 43

<...>

De kolom mogelijke_sleutels beschrijft de mogelijke indexen die MySQL kan kiezen, de kolom sleutel beschrijft de daadwerkelijk gekozen index en de kolom sleutel_len beschrijft de lengte van de gekozen sleutel.

In dit geval zou MySQL de waarden in de index opzoeken en alle rijen retourneren die de opgegeven waarde bevatten - als resultaat zou de query sneller zijn. Hoewel indexen ervoor zorgen dat bepaalde zoekopdrachten sneller worden uitgevoerd, zijn er een aantal dingen waarmee u rekening moet houden als u wilt dat uw indexen uw zoekopdrachten ondersteunen:

  • Isoleer uw kolommen - MySQL kan geen indexen gebruiken als de kolommen waarop de indexen worden gebruikt niet geïsoleerd zijn. Een zoekopdracht als deze zou bijvoorbeeld geen index gebruiken:
    SELECT field_1 FROM demo_table WHERE field_1 + 5 = 10;

Om dit op te lossen, laat u de kolom achter de WHERE-clausule alleen staan ​​- vereenvoudig uw zoekopdracht zo veel mogelijk en isoleer de kolommen;

  • Vermijd het gebruik van LIKE-query's met een voorafgaand jokerteken - in dit geval zal MySQL geen index gebruiken omdat het voorgaande jokerteken betekent dat er iets voor de tekst kan staan. Als u LIKE-query's met jokertekens moet gebruiken en u wilt dat de query's gebruik maken van indexen, zorg er dan voor dat het jokerteken aan het einde van de zoekopdracht staat.

Het versnellen van zoekopdrachten die overeenkomen met een WHERE-clausule kan natuurlijk ook op andere manieren worden gedaan (bijvoorbeeld partitioneren), maar omwille van de eenvoud gaan we daar in dit bericht niet verder op in.

Waar we echter in geïnteresseerd kunnen zijn, zijn verschillende soorten indextypen, dus daar gaan we nu naar kijken.

Dubbele waarden in een kolom verwijderen - UNIEKE indexen

Het doel van een UNIEKE index in MySQL is om de uniciteit van de waarden in een kolom af te dwingen. Voer een CREATE UNIQUE INDEX-query uit om een ​​UNIEKE index te gebruiken:

CREATE UNIQUE INDEX demo_index ON demo_table(demo_column);

You can also create a unique index when you create a table:

CREATE TABLE demo_table (
`demo_column` VARCHAR(100) NOT NULL,
UNIQUE KEY(demo_column)
);

Dat is alles wat nodig is om een ​​unieke index aan een tabel toe te voegen. Wanneer u nu een dubbele waarde aan de tabel probeert toe te voegen, komt MySQL terug met de volgende fout:

#1062 - Duplicate entry ‘Demo’ for key ‘demo_column’

FULLTEXT-indexen

Een FULLTEXT-index is zo'n index die wordt toegepast op de kolommen die full-text zoekmogelijkheden gebruiken. Dit type index heeft veel unieke mogelijkheden, waaronder stopwoorden en zoekmodi.

De InnoDB-stopwoordenlijst heeft 36 woorden, terwijl de MyISAM-stopwoordenlijst 143 woorden heeft. In InnoDB zijn de stopwoorden afgeleid van de tabel die is ingesteld in de variabele innodb_ft_user_stopword_table, anders, als deze variabele niet is ingesteld, worden ze afgeleid van de innodb_ft_server_stopword_table variabele. Als geen van deze twee variabelen is ingesteld, gebruikt InnoDB de ingebouwde lijst. Vraag de INNODB_FT_DEFAULT_STOPWORD-tabel om de standaard InnoDB-stopwoordenlijst te zien.

In MyISAM zijn de stopwoorden afgeleid van het bestand storage/myisam/ft_static.c. Met de variabele ft_stopword_file kan de standaard stopwoordenlijst worden gewijzigd. Stopwoorden worden uitgeschakeld als deze variabele is ingesteld op een lege tekenreeks, maar houd er rekening mee dat als deze variabele een bestand definieert, het gedefinieerde bestand niet wordt geparseerd voor opmerkingen - MyISAM behandelt alle woorden in het bestand als stopwoorden.

De FULLTEXT-indexen staan ​​ook bekend om hun unieke zoekmodi:

  • Als een FULLTEXT-zoekopdracht zonder modifiers wordt uitgevoerd, wordt een natuurlijke taalmodus geactiveerd. De natuurlijke taalmodus kan ook worden geactiveerd met behulp van de IN NATUURLIJKE TAALMODUS-modifier;
  • De WITH QUERY EXPANSION-modifier maakt een zoekmodus met query-uitbreiding mogelijk. Een dergelijke zoekmodus werkt door de zoekopdracht twee keer uit te voeren en wanneer de zoekopdracht voor de tweede keer wordt uitgevoerd, bevat de resultatenset enkele van de meest relevante documenten van de eerste zoekopdracht. Over het algemeen is deze modifier handig wanneer de gebruiker enige impliciete kennis heeft (de gebruiker kan bijvoorbeeld zoeken naar "database" en hopen "InnoDB" en "MyISAM" in de resultatenset te zien);
  • De IN BOOLEAN MODE-modifier maakt zoeken met Booleaanse operatoren mogelijk. De operatoren +, - of * zouden bijvoorbeeld elk verschillende taken uitvoeren - de operator + zou definiëren dat de waarde in een rij aanwezig moet zijn, de operator - zou definiëren dat de waarde niet mag bestaan ​​en de operator * zou fungeren als een jokerteken.

Een zoekopdracht die een FULLTEXT-index gebruikt, ziet er als volgt uit:

SELECT * FROM demo_table WHERE MATCH(demo_field) AGAINST(‘value’ IN NATURAL LANGUAGE MODE);

Houd er rekening mee dat FULLTEXT-indexen over het algemeen handig zijn voor MATCH() AGAINST()-bewerkingen - niet voor WHERE-bewerkingen, wat betekent dat als een WHERE-clausule zou worden gebruikt, het nut van het gebruik van verschillende indextypes zou niet worden geëlimineerd.

Het is ook vermeldenswaard dat FULLTEXT-indexen een minimale lengte van tekens hebben. In InnoDB kan een FULLTEXT-zoekopdracht alleen worden uitgevoerd als de zoekopdracht uit minimaal drie tekens bestaat - deze limiet wordt verhoogd tot vier tekens in de MyISAM-opslagengine.

AFALENDE Indexen

Een DESCENDING index is zo'n index waar InnoDB de items in een aflopende volgorde opslaat - de query-optimizer zal een dergelijke index gebruiken wanneer een aflopende volgorde wordt gevraagd door de query. Een dergelijke index kan aan een kolom worden toegevoegd door een zoekopdracht uit te voeren zoals hieronder:

CREATE INDEX descending_index ON demo_table(column_name DESC);

Een oplopende index kan ook aan een kolom worden toegevoegd - vervang gewoon DESC door ASC.

PRIMAIRE SLEUTELS

EEN PRIMAIRE SLEUTEL dient als een unieke identificatie voor elke rij in een tabel. Een kolom met een PRIMARY KEY moet unieke waarden bevatten - er mogen ook geen NULL-waarden worden gebruikt. Als een dubbele waarde wordt toegevoegd aan een kolom die een PRIMAIRE SLEUTEL heeft, reageert MySQL met een fout #1062:

#1062 - Duplicate entry ‘Demo’ for key ‘PRIMARY’

Als een NULL-waarde aan de kolom wordt toegevoegd, reageert MySQL met een fout #1048:

#1048 - Column ‘id’ cannot be null

Primaire indexen worden soms ook geclusterde indexen genoemd (we bespreken ze later).

U kunt ook indexen voor meerdere kolommen tegelijk maken - dergelijke indexen worden multikolomindexen genoemd.

Indexen met meerdere kolommen

Indexen op meerdere kolommen worden vaak verkeerd begrepen - soms indexeren ontwikkelaars en DBA's alle kolommen afzonderlijk of indexeren ze in de verkeerde volgorde. Om query's die gebruik maken van indexen met meerdere kolommen zo effectief mogelijk te maken, moet u er rekening mee houden dat de volgorde van kolommen in indexen die meer dan één kolom gebruiken een van de meest voorkomende oorzaken van verwarring is in deze ruimte - aangezien er geen "deze kant of de snelweg is". ” indexvolgorde-oplossingen, moet u onthouden dat de juiste volgorde van indexen met meerdere kolommen afhankelijk is van de query's die de index gebruiken. Hoewel dit vrij voor de hand liggend lijkt, moet u er rekening mee houden dat de kolomvolgorde van vitaal belang is bij het omgaan met indexen met meerdere kolommen - kies de kolomvolgorde zo dat deze zo selectief mogelijk is voor de zoekopdrachten die het vaakst worden uitgevoerd.

Om de selectiviteit voor specifieke kolommen te meten, moet u de verhouding krijgen tussen het aantal afzonderlijke geïndexeerde waarden en het totale aantal rijen in de tabel - de kolom met de hoogste selectiviteit moet de eerste zijn .

Soms moet je ook erg lange karakterkolommen indexeren, en in dat geval kun je vaak tijd en middelen besparen door de eerste paar karakters - een prefix - te indexeren in plaats van de hele waarde.

Voorvoegselindexen

Prefix-indexen kunnen handig zijn als de kolommen erg lange tekenreekswaarden bevatten, wat zou betekenen dat het toevoegen van een index aan de hele kolom veel schijfruimte zou kosten. MySQL helpt dit probleem aan te pakken doordat u alleen een voorvoegsel van de waarde kunt indexeren, waardoor de index kleiner wordt. Kijk eens:

CREATE TABLE `demo_table` (
`demo_column` VARCHAR(100) NOT NULL,
INDEX(demo_column(10))
);

De bovenstaande query zou een prefix-index maken in de demokolom die alleen de eerste 10 tekens van de waarde indexeert. U kunt ook een prefix-index toevoegen aan een bestaande tabel:

CREATE INDEX index_name ON table_name(column_name(length));

Dus als u bijvoorbeeld de eerste 5 tekens van een demo_column op een demo_table wilt indexeren, kunt u de volgende query uitvoeren:

CREATE INDEX demo_index ON demo_table(demo_column(5));

Je moet een voorvoegsel kiezen dat lang genoeg is om selectiviteit te geven, maar ook kort genoeg om ruimte te geven. Dit is misschien makkelijker gezegd dan gedaan - je moet experimenteren en de oplossing vinden die voor jou werkt.

Indexen afdekken

Een dekkende index "dekt" alle vereiste velden om een ​​zoekopdracht uit te voeren. Met andere woorden, wanneer alle velden in een zoekopdracht door een index worden gedekt, is er een dekkende index in gebruik. Bijvoorbeeld voor een zoekopdracht als volgt:

SELECT id, title FROM demo_table WHERE id = 1;

Een dekkende index kan er als volgt uitzien:

INDEX index_name(id, title);

Als je er zeker van wilt zijn dat een zoekopdracht een dekkingsindex gebruikt, geef er dan een EXPLAIN-instructie op en kijk in de kolom Extra. Als uw tabel bijvoorbeeld een index met meerdere kolommen heeft op id en titel en er wordt een query uitgevoerd die alleen toegang heeft tot deze twee kolommen, dan zal MySQL de index gebruiken:

mysql> EXPLAIN SELECT id, title FROM demo_table \G;

*************************** 1. row ***************************

<...>

type: index

key: index_name

key_len: 5

rows: 1000

Extra: Using index

<...>

Houd er rekening mee dat een dekkende index de waarden moet opslaan van de kolommen die het beslaat. Dat betekent dat MySQL alleen B-Tree-indexen kan gebruiken om zoekopdrachten te dekken, omdat andere soorten indexen deze waarden niet opslaan.

Geclusterde, secundaire indexen en indexkardinaliteit

Als indexen worden besproken, hoor je mogelijk ook de termen geclusterd, secundaire indexen en indexkardinaliteit. Simpel gezegd, geclusterde indexen zijn een benadering van gegevensopslag en alle andere indexen dan geclusterde indexen zijn secundaire indexen. Indexkardinaliteit daarentegen is het aantal unieke waarden in een index.

Een geclusterde index versnelt zoekopdrachten omdat waarden die dicht bij elkaar liggen ook dicht bij elkaar op de schijf worden opgeslagen, maar dat is ook de reden waarom je maar één geclusterde index in een tabel kunt hebben.

Een secundaire index is een index die niet de primaire index is. Zo'n index kan duplicaten bevatten.

De nadelen van het gebruik van indexen

Het gebruik van indexen heeft zeker voordelen, maar we mogen niet vergeten dat indexen ook een van de belangrijkste oorzaken van problemen in MySQL kunnen zijn. Enkele nadelen van het gebruik van indexen zijn:

  • Indexen kunnen de prestaties van bepaalde query's verminderen - hoewel indexen de prestatie van SELECT-query's meestal versnellen, vertragen ze de prestatie van INSERT-, UPDATE- en DELETE-query's, omdat wanneer de gegevens worden bijgewerkt de index moet ook samen ermee worden bijgewerkt:elke bewerking waarbij de indexen worden gemanipuleerd, zal langzamer zijn dan normaal;
  • Indexen verbruiken schijfruimte - een index neemt zijn eigen ruimte in beslag, dus geïndexeerde gegevens zullen ook meer schijfruimte in beslag nemen;
  • Overbodige en dubbele indexen kunnen een probleem zijn - MySQL stelt u in staat om dubbele indexen op een kolom te maken en het "beschermt u" niet tegen het maken van een dergelijke fout. Bekijk dit voorbeeld:
    CREATE TABLE `demo_table` (
    
    `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    
    `column_2` VARCHAR(10) NOT NULL,
    
    `column_3` VARCHAR(10) NOT NULL,
    
    INDEX(id),
    
    UNIQUE(id)
    
    );

Een onervaren gebruiker zou kunnen denken dat deze query de id-kolom automatisch laat toenemen, vervolgens een index aan de kolom toevoegt en ervoor zorgt dat de kolom geen dubbele waarden accepteert. Dit is echter niet wat hier gebeurt. In dit geval heeft dezelfde kolom drie indexen:een gewone INDEX, en aangezien MySQL zowel PRIMARY KEY als UNIQUE-beperkingen met indexen implementeert, voegt dat nog twee indexen toe aan dezelfde kolom!

Conclusie

Tot slot, indexen in MySQL hebben hun eigen plaats - indexen kunnen in een groot aantal scenario's worden gebruikt, maar elk van die gebruiksscenario's heeft zijn eigen nadelen waarmee rekening moet worden gehouden om het meeste uit te halen indexen die in gebruik zijn.

Om indexen goed te gebruiken, profileert u uw zoekopdrachten, bekijkt u welke opties u heeft als het gaat om indexen, kent u hun voor- en nadelen, bepaalt u welke indexen u nodig heeft op basis van uw vereisten en nadat u de kolommen hebt geïndexeerd, zorgt u ervoor dat uw indexen daadwerkelijk gebruikt door MySQL. Als je je schema goed hebt geïndexeerd, zouden de prestaties van je zoekopdrachten moeten verbeteren, maar als de responstijd je niet bevredigt, kijk dan of er een betere index kan worden gemaakt om deze te verbeteren.


  1. Common Sense-licentiewijzigingen voor SQL Server 2014 Standard Edition

  2. MySQL dynamische-pivot

  3. UUID-string formatteren zonder REGEXP_REPLACE en PL/SQL

  4. Deel 2:Beeldclassificatie met MariaDB Server en TensorFlow - een zelfstudie