sql >> Databáze >  >> RDS >> Mysql

Jak fungují indexy MySQL?

První věc, kterou musíte vědět, je, že indexy jsou způsob, jak se vyhnout skenování celé tabulky, abyste získali výsledek, který hledáte.

Existují různé druhy indexů a jsou implementovány ve vrstvě úložiště, takže mezi nimi neexistuje žádný standard a také závisí na úložném enginu, který používáte.

InnoDB a index B+Tree

Pro InnoDB je nejběžnějším typem indexu index založený na B+Tree, který ukládá prvky v seřazeném pořadí. Také nemusíte přistupovat ke skutečné tabulce, abyste získali indexované hodnoty, díky čemuž se váš dotaz vrátí mnohem rychleji.

"Problém" tohoto typu indexu spočívá v tom, že pro použití indexu je nutné zadat dotaz na hodnotu zcela vlevo. Pokud tedy váš index obsahuje dva sloupce, řekněme last_name a first_name, velmi záleží na pořadí dotazu na tato pole. .

Takže s ohledem na následující tabulku:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

Tento dotaz by využil index:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

Ale následující by ne

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

Protože se ptáte na first_name sloupec první a není to sloupec úplně vlevo v indexu.

Tento poslední příklad je ještě horší:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

Protože nyní porovnáváte pravou část pole zcela vpravo v indexu.

Hash index

Toto je jiný typ indexu, který bohužel podporuje pouze paměťový backend. Je bleskurychlý, ale užitečný pouze pro úplné vyhledávání, což znamená, že jej nemůžete použít pro operace jako > , < nebo LIKE .

Vzhledem k tomu, že funguje pouze pro paměťový backend, pravděpodobně jej nebudete používat příliš často. Hlavní případ, který mě právě napadá, je ten, že vytvoříte dočasnou tabulku v paměti se sadou výsledků z jiného výběru a provedete spoustu dalších výběrů v této dočasné tabulce pomocí hash indexů.

Pokud máte velký VARCHAR pole, můžete "emulovat" použití hash indexu při použití B-stromu vytvořením dalšího sloupce a uložením hash velké hodnoty do něj. Řekněme, že ukládáte adresu URL do pole a hodnoty jsou poměrně velké. Můžete také vytvořit celočíselné pole s názvem url_hash a použijte hashovací funkci jako CRC32 nebo jakákoli jiná hashovací funkce pro hashování adresy URL při jejím vkládání. A pak, když potřebujete dotaz na tuto hodnotu, můžete udělat něco takového:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

Problém s výše uvedeným příkladem je, že od CRC32 Funkce generuje poměrně malý hash, skončíte s mnoha kolizemi v hašovaných hodnotách. Pokud potřebujete přesné hodnoty, můžete tento problém vyřešit takto:

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

Stále stojí za to věci hašovat, i když je číslo kolize vysoké, protože provedete pouze druhé porovnání (řetězcové) s opakovanými hašemi.

Bohužel při použití této techniky je stále potřeba trefit se do tabulky, abyste mohli porovnat url pole.

Zabalit

Některá fakta, která můžete vzít v úvahu pokaždé, když budete chtít mluvit o optimalizaci:

  1. Porovnání celých čísel je mnohem rychlejší než porovnání řetězců. Lze to ilustrovat na příkladu emulace hash indexu v InnoDB .

  2. Možná, že přidáním dalších kroků do procesu je proces rychlejší, nikoli pomalejší. Lze to ilustrovat tím, že můžete optimalizovat SELECT rozdělením do dvou kroků, přičemž první ukládá hodnoty do nově vytvořené tabulky v paměti a poté provádí těžší dotazy na této druhé tabulce.

MySQL má i jiné indexy, ale myslím si, že ten B+Tree je nejpoužívanější a ten hash je dobré vědět, ale ty ostatní najdete v Dokumentace MySQL .

Vřele vám doporučuji, abyste si přečetli knihu „High Performance MySQL“, výše uvedená odpověď byla rozhodně založena na její kapitole o indexech.



  1. Datatyp Oracle Date, transformovaný na 'YYYY-MM-DD HH24:MI:SS TMZ' prostřednictvím SQL

  2. Přiřazení obrázků k položkám ListView Výukový program-03

  3. Proč PostgreSQL sloučil uživatele a skupiny do rolí?

  4. Podivné duplicitní chování z GROUP_CONCAT ze dvou LEFT JOINů ze GROUP_BYs