MariaDB
 sql >> база данни >  >> RDS >> MariaDB

Ръководство за MySQL индекси

Когато се спомене оптимизация на MySQL заявки, индексите са едно от първите неща, които се покриват. Днес ще се опитаме да разберем защо те са толкова важни.

Какво са индексите?

По принцип индексът е азбучен списък от записи с препратки към страниците, на които са споменати. В MySQL индексът е структура от данни, използвана за бързо намиране на редове. Индексите се наричат ​​още ключове и тези ключове са от решаващо значение за добрата производителност - тъй като данните се увеличават, необходимостта от правилно използване на индекси може да стане все по-важна. Използването на индекси е един от най-мощните начини за подобряване на производителността на заявката – ако индексите се използват правилно, производителността на заявката може да се увеличи с десетки или дори стотици пъти.

Днес ще се опитаме да обясним основните предимства и недостатъци на използването на индекси в MySQL. Имайте предвид, че MySQL индексите сами по себе си заслужават цяла книга, така че тази публикация няма да обхваща абсолютно всичко, но ще бъде добра отправна точка. За тези, които се интересуват от това как работят индексите на по-дълбоко ниво, четенето на книгата „Дизайн на индекс на релационна база данни и оптимизатори“ от Тапио Лахденмаки и Майкъл Лийч би трябвало да даде повече представа.

Предимствата от използването на индекси

Има няколко основни предимства от използването на индекси в MySQL и те са както следва:

  • Индексите позволяват бързо намиране на редове, съответстващи на клауза WHERE;
  • Индексите могат да помогнат на заявките да избегнат търсенето в определени редове, като по този начин намаляват количеството данни, които сървърът трябва да проучи - ако има избор между множество индекси, MySQL обикновено използва най-селективния индекс, т.е. индекс, който намира най-малкото количество редове;
  • Могат да се използват индекси за извличане на редове от други таблици в операции JOIN;
  • Индексите може да се използват за намиране на минималната или максималната стойност на конкретна колона, която използва индекс;
  • Индексите могат да се използват за сортиране или групиране на таблица, ако операциите се извършват върху най-левия префикс на индекс - по подобен начин, най-левият префикс на индекс с множество колони може също да се използва от оптимизатора на заявки за търсене на редове;
  • Индексите могат да се използват и за запазване на дисков вход/изход – когато се използва покриващ индекс, заявката може да върне стойности направо от структурата на индекса, спестявайки дисков вход/изход.

По същия начин има няколко типа индекси:

  • ИНДЕКС е тип индекс, при който стойностите не трябва да са уникални. Този тип индекс приема стойности NULL;
  • UNIQUE INDEX често се използва за премахване на дублиращи се редове от таблица - този тип индекс позволява на разработчиците да наложат уникалността на стойностите на редовете;
  • ПЪЛНОТЕКСТОВ ИНДЕКС е индекс, който се прилага към полета, които използват възможности за пълнотекстово търсене. Този тип индекс намира ключови думи в текста, вместо директно да сравнява стойностите със стойностите в индекса;
  • НИЗЯЩ ИНДЕКС е индекс, който съхранява редове в низходящ ред - оптимизаторът на заявки ще избере този тип индекс, когато заявката е поискала низходящ ред. Този тип индекс е въведен в MySQL 8.0;
  • ПЪРВИЧНИЯ КЛЮЧ също е индекс. Накратко, ПЪРВИЧНИЯ КЛЮЧ е колона или набор от колони, които идентифицират всеки ред в таблицата – често се използва заедно с полета с атрибут AUTO_INCREMENT. Този тип индекс не приема стойности NULL и веднъж зададени, стойностите в ПЪРВИЧНИЯ КЛЮЧ не могат да бъдат променени.

Сега ще се опитаме да разгледаме както предимствата, така и недостатъците на използването на индекси в MySQL. Ще започнем с вероятно най-често обсъжданата обратна страна – ускоряване на заявки, които съответстват на клауза WHERE.

Ускоряване на заявки, съответстващи на клауза WHERE

Индексите често се използват за ускоряване на заявки за търсене, които съответстват на клауза WHERE. Причината, поради която индексът прави подобни операции за търсене по-бързи, е доста проста – заявките, които използват индекс, избягват пълно сканиране на таблицата.

За да ускорите заявките, които съответстват на клауза WHERE, можете да използвате израза EXPLAIN в MySQL. Изявлението EXPLAIN SELECT трябва да ви даде известна представа за това как MySQL оптимизаторът на заявки изпълнява заявката - може също да ви покаже дали въпросната заявка използва индекс или не и какъв индекс използва. Разгледайте следното обяснение на заявката:

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

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

<...>

possible_keys: NULL

key: NULL

key_len: NULL

<...>

Горената заявка не използва индекс. Въпреки това, ако добавим индекс към „field_1“, индексът ще бъде използван успешно:

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

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

<...>

possible_keys: field_1

key: field_1

key_len: 43

<...>

Колоната possible_keys описва възможните индекси, които MySQL може да избере, колоната key описва действително избрания индекс, а колоната key_len описва дължината на избрания ключ.

В този случай MySQL ще извърши търсене на стойностите в индекса и ще върне всички редове, съдържащи посочената стойност - в резултат на това заявката ще бъде по-бърза. Въпреки че индексите помагат на определени заявки да бъдат по-бързи, има няколко неща, които трябва да имате предвид, ако искате вашите индекси да помагат на вашите заявки:

  • Изолирайте колоните си - MySQL не може да използва индекси, ако колоните, в които се използват индексите, не са изолирани. Например, заявка като тази няма да използва индекс:
    SELECT field_1 FROM demo_table WHERE field_1 + 5 = 10;

За да разрешите това, оставете колоната, която върви след клаузата WHERE, сама – опростете заявката си колкото е възможно повече и изолирайте колоните;

  • Избягвайте да използвате LIKE заявки с предходен заместващ знак - в този случай MySQL няма да използва индекс, защото предходният заместващ знак означава, че може да има всичко преди текста. Ако трябва да използвате заявки LIKE със заместващи знаци и искате заявките да използват индекси, уверете се, че заместващият знак е в края на израза за търсене.

Разбира се, ускоряването на заявки, които съответстват на клауза WHERE, може да се направи и по други начини (например разделяне), но с цел простота няма да разглеждаме това по-нататък в тази публикация.

Това, което може да ни интересува обаче, са различни видове индекси, така че сега ще разгледаме това.

Премахване на дублиращи се стойности в колона – УНИКАЛНИ индекси

Целта на УНИКАЛЕН индекс в MySQL е да наложи уникалността на стойностите в колона. За да използвате UNIQUE индекс, изпълнете заявка CREATE UNIQUE INDEX:

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)
);

Това е всичко, което е необходимо, за да добавите уникален индекс към таблица. Сега, когато се опитате да добавите дублирана стойност към таблицата, MySQL ще се върне със следната грешка:

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

ПЪЛНОТЕКСТОВИ Индекси

ПЪЛНОТЕКСТОВ Индекс е такъв индекс, който се прилага към колоните, които използват възможности за пълнотекстово търсене. Този тип индекс има много уникални възможности, включително спиращи думи и режими на търсене.

Списъкът със спирателни думи на InnoDB има 36 думи, докато списъкът със стоп думи на MyISAM има 143. В InnoDB спирателните думи се извличат от таблицата, зададена в променливата innodb_ft_user_stopword_table, в противен случай, ако тази променлива не е зададена, те се извличат от променливата innodb_ft_server_stopword_table. Ако нито една от тези две променливи не е зададена, InnoDB използва вградения списък. За да видите списъка със спиращи думи на InnoDB по подразбиране, потърсете таблицата INNODB_FT_DEFAULT_STOPWORD.

В MyISAM спирателните думи се извличат от файла storage/myisam/ft_static.c. Променливата ft_stopword_file позволява промяната на списъка със стоп думи по подразбиране. Стоп думите ще бъдат деактивирани, ако тази променлива е зададена на празен низ, но имайте предвид, че ако тази променлива дефинира файл, дефинираният файл не се анализира за коментари - MyISAM ще третира всички думи, намерени във файла, като стоп думи.

Индексите FULLTEXT са известни и със своите уникални режими на търсене:

  • Ако се изпълни заявка за търсене FULLTEXT без модификатори, ще бъде активиран режим на естествен език. Режимът на естествен език може да бъде активиран и с помощта на модификатора IN NATURAL LANGUAGE MODE;
  • Модификаторът WITH QUERY EXPANSION активира режим на търсене с разширяване на заявката. Такъв режим на търсене работи, като извършва търсенето два пъти и когато търсенето се стартира за втори път, наборът от резултати ще включва няколко от най-подходящите документи от първото търсене. Като цяло, този модификатор е полезен, когато потребителят има някакви подразбиращи се познания (например, потребителят може да търси „база данни“ и да се надява да види „InnoDB“ и „MyISAM“ в набора от резултати);
  • Модификаторът IN BOOLEAN MODE позволява търсене с булеви оператори. Например, всеки от операторите +, - или * ще изпълнява различни задачи - операторът + ще дефинира, че стойността трябва да присъства в ред, операторът - ще дефинира, че стойността не трябва да съществува, а операторът * ще действа като заместващ знак.

Заявка, която използва индекс FULLTEXT, изглежда така:

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

Имайте предвид, че индексите FULLTEXT обикновено са полезни за операции MATCH() AGAINST() - не за операции WHERE, което означава, че ако се използва клауза WHERE, полезността от използването на различни типове индекси няма да бъде елиминирана.

Също така си струва да се спомене, че индексите FULLTEXT имат минимална дължина на знаците. В InnoDB търсенето с ПЪЛЕН текст може да се извърши само когато заявката за търсене се състои от минимум три знака - това ограничение се увеличава до четири знака в механизма за съхранение на MyISAM.

НИЗАЩИ Индекси

НИЗЯЩ Индекс е такъв индекс, при който InnoDB съхранява записите в низходящ ред - оптимизаторът на заявки ще използва такъв индекс, когато заявката е поискала низходящ ред. Такъв индекс може да бъде добавен към колона чрез изпълнение на заявка, както следва:

CREATE INDEX descending_index ON demo_table(column_name DESC);

В колона може да се добави и възходящ индекс - просто заменете DESC с ASC.

ПЪРВИЧНИ КЛЮЧОВЕ

ПЪРВИЧЕН КЛЮЧ служи като уникален идентификатор за всеки ред в таблица. Колона с ПЪРВИЧЕН КЛЮЧ трябва да съдържа уникални стойности - също не е позволено да се използват NULL стойности. Ако се добави дублирана стойност към колона, която има ПЪРВИЧЕН КЛЮЧ, MySQL ще отговори с грешка #1062:

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

Ако към колоната се добави стойност NULL, MySQL ще отговори с грешка #1048:

#1048 - Column ‘id’ cannot be null

Първичните индекси също понякога се наричат ​​клъстерирани индекси (ще ги обсъждаме по-късно).

Можете също да създавате индекси за множество колони наведнъж - такива индекси се наричат ​​многоколонови индекси.

Многоколонови индекси

Индексите на множество колони често се разбират погрешно – понякога разработчиците и администраторите на база данни индексират всички колони поотделно или ги индексират в грешен ред. За да направите заявките, използващи индекси с няколко колони, възможно най-ефективни, не забравяйте, че редът на колоните в индексите, които използват повече от една колона, е една от най-честите причини за объркване в това пространство - тъй като няма „този път или магистрала ” решения за реда на индекси, трябва да запомните, че правилният ред на многоколонните индекси зависи от заявките, които използват индекса. Въпреки че това може да изглежда доста очевидно, не забравяйте, че редът на колоните е жизненоважен, когато работите с индекси с няколко колони – изберете реда на колоните, така че да е възможно най-селективен за заявките, които ще се изпълняват най-често.

За да измерите селективността за конкретни колони, вземете съотношението на броя на отделните индексирани стойности към общия брой редове в таблицата - колоната с по-висока селективност трябва да бъде първата .

Понякога трябва да индексирате и колони с много дълги знаци и в този случай често можете да спестите време и ресурси, като индексирате първите няколко знака – префикс – вместо цялата стойност.

Префиксни индекси

Префиксните индекси могат да бъдат полезни, когато колоните съдържат много дълги низови стойности, което би означавало, че добавянето на индекс към цялата колона ще заеме много дисково пространство. MySQL помага за справяне с този проблем, като ви позволява да индексирате само префикс на стойността, което от своя страна прави размера на индекса по-малък. Разгледайте:

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

Горената заявка ще създаде префиксен индекс в демонстрационната колона, индексиращ само първите 10 знака от стойността. Можете също да добавите префиксен индекс към съществуваща таблица:

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

Така че, например, ако искате да индексирате първите 5 знака от demo_column в demo_table, можете да изпълните следната заявка:

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

Трябва да изберете префикс, който е достатъчно дълъг, за да даде селективност, но и достатъчно къс, за да даде място. Това обаче може да е по-лесно да се каже, отколкото да се направи – трябва да експериментирате и да намерите решението, което работи за вас.

Покриващи индекси

Покриващ индекс „покрива“ всички необходими полета за изпълнение на заявка. С други думи, когато всички полета в една заявка са покрити от индекс, се използва покриващ индекс. Например за заявка като така:

SELECT id, title FROM demo_table WHERE id = 1;

Покриващ индекс може да изглежда така:

INDEX index_name(id, title);

Ако искате да сте сигурни, че дадена заявка използва покриващ индекс, издайте за нея оператор EXPLAIN, след което погледнете колоната Extra. Например, ако вашата таблица има многоколонен индекс за идентификатор и заглавие и се изпълнява заявка, която има достъп само до тези две колони, MySQL ще използва индекса:

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

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

<...>

type: index

key: index_name

key_len: 5

rows: 1000

Extra: Using index

<...>

Имайте предвид, че покриващият индекс трябва да съхранява стойностите от колоните, които покрива. Това означава, че MySQL може да използва само индекси на B-Tree за покриване на заявки, тъй като други видове индекси не съхраняват тези стойности.

Клъстерни, вторични индекси и мощност на индекса

Когато се обсъждат индекси, може да чуете и термините групирани, вторични индекси и мощност на индекса. Казано по-просто, клъстерираните индекси са подход към съхранението на данни и всички индекси, различни от клъстерираните индекси, са вторични индекси. Кардиналността на индекса от друга страна е броят на уникалните стойности в индекс.

Клъстерираният индекс ускорява заявките, тъй като близките стойности също се съхраняват близо една до друга на диска, но това е и причината, поради която можете да имате само един клъстериран индекс в таблица.

Вторичен индекс е всеки индекс, който не е основният индекс. Такъв индекс може да има дубликати.

Недостатъците при използването на индекси

Използването на индекси със сигурност има положителни страни, но не трябва да забравяме, че индексите също могат да бъдат една от водещите причини за проблеми в MySQL. Някои от недостатъците на използването на индекси са както следва:

  • Индексите могат да влошат производителността на определени заявки - въпреки че индексите са склонни да ускоряват производителността на SELECT заявките, те забавят производителността на заявките INSERT, UPDATE и DELETE, защото когато данните се актуализират, индексът също трябва да бъде актуализиран заедно с него:всяка операция, която включва манипулиране на индексите, ще бъде по-бавна от обикновено;
  • Индексите заемат дисково пространство – индексът заема собствено пространство, така че индексираните данни също ще заемат повече дисково пространство;
  • Излишните и дублиращи се индекси могат да бъдат проблем - MySQL ви позволява да създавате дублиращи се индекси в колона и не ви „предпазва“ от такава грешка. Разгледайте този пример: 
    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)
    
    );

Неопитен потребител може да си помисли, че тази заявка кара колоната с идентификатор да се увеличава автоматично, след което добавя индекс към колоната и кара колоната да не приема дублиращи се стойности. Това обаче не е това, което се случва тук. В този случай една и съща колона има три индекса:обикновен INDEX и тъй като MySQL прилага както ограниченията PRIMARY KEY, така и UNIQUE с индекси, това добавя още два индекса към същата колона!

Заключение

В заключение, индексите в MySQL имат свое собствено място - индексите могат да се използват в множество сценарии, но всеки от тези сценарии на използване има свои собствени недостатъци, които трябва да се вземат предвид, за да се извлече максимална полза индекси, които се използват.

За да използвате добре индексите, профилирайте заявките си, разгледайте какви опции имате, когато става въпрос за индекси, знайте техните предимства и недостатъци, решете какви индекси имате нужда въз основа на вашите изисквания и след като индексирате колоните, се уверете, че вашите индекси са всъщност се използва от MySQL. Ако сте индексирали схемата си правилно, производителността на вашите заявки трябва да се подобри, но ако времето за отговор не ви удовлетворява, вижте дали може да се създаде по-добър индекс, за да се подобри.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 3 начина да получите името на деня от дата в MariaDB

  2. MariaDB ще представи TO_CHAR()

  3. Как да шифровате вашите MySQL и MariaDB архиви

  4. Как да върнете номера на деня с суфикс в MariaDB

  5. 6 начина да проверите вашата версия на MariaDB