Как работают индексы MySQL?
Мне действительно интересно, как работают индексы MySQL, а точнее, как они могут вернуть запрошенные данные без сканирования всей таблицы?
Это не по теме, я знаю, но если есть кто-то, кто мог бы объяснить это мне подробно, я был бы очень, очень благодарен.
Ответы
Ответ 1
В основном индекс в таблице работает как индекс в книге (откуда пришло имя):
Скажем, у вас есть книга о базах данных, и вы хотите найти некоторую информацию, например, о хранилище. Без индекса (без дополнительной помощи, например, оглавления) вам придется проходить страницы один за другим, пока не найдете тему ().
С другой стороны, индекс имеет список ключевых слов, поэтому вы обратитесь к индексу и увидите, что storage
упоминается на страницах 113-120, 231 и 354. Затем вы можете напрямую переходить на эти страницы без поиска (что поиск с индексом, несколько быстрее).
Конечно, насколько полезен индекс, зависит от многих вещей - несколько примеров, используя сравнение выше:
- Если у вас есть книга по базам данных и проиндексирована слово "база данных", вы увидите, что она упоминается на страницах 1-59,61-290 и 292-400. В этом случае индекс не очень помогает и, возможно, быстрее перейти через страницы один за другим (в базе данных это "низкая избирательность" ).
- Для 10-страничной книги нет смысла делать индекс, так как вы можете получить 10-страничную книгу с префиксом 5 страниц, что просто глупо - просто сканируйте 10 страниц и будьте с ним.
- Индекс также должен быть полезен - обычно нет точки для индекса, например. частота буквы "L" на странице.
Ответ 2
Первое, что вы должны знать, это то, что индексы - это способ избежать сканирования всей таблицы, чтобы получить результат, который вы ищете.
Существуют разные типы индексов, и они реализованы на уровне хранилища, поэтому между ними нет стандарта, и они также зависят от используемого вами механизма хранения.
InnoDB и индекс дерева B +
Для InnoDB наиболее распространенным типом индекса является индекс B + Tree, который хранит элементы в отсортированном порядке. Кроме того, вам не нужно обращаться к реальной таблице, чтобы получить индексированные значения, что ускоряет возврат запроса.
"Проблема" в этом типе индекса заключается в том, что вам нужно запросить самое левое значение для использования индекса. Итак, если ваш индекс имеет два столбца, скажем last_name и first_name, порядок, который вы запрашиваете для этих полей , имеет значение.
Итак, учитывая следующую таблицу:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
В этом запросе будет использоваться индекс:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Но следующий не будет
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Потому что вы сначала запрашиваете столбец first_name
, а не самый левый столбец в индексе.
Этот последний пример еще хуже:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Потому что теперь вы сравниваете правую часть самого правого поля в индексе.
Хэш-индекс
Это другой тип индекса, который, к сожалению, поддерживает только память. Он молниеносно, но полезен только для полного поиска, а это значит, что вы не можете использовать его для операций типа >
, <
или LIKE
.
Так как он работает только для бэкэда памяти, вы, вероятно, не будете его использовать очень часто. Основной случай, о котором я могу сейчас думать, - это создать временную таблицу в памяти с помощью набора результатов из другого select и выполнить множество других выборок в этой временной таблице с использованием индексов хеша.
Если у вас большое поле VARCHAR
, вы можете "эмулировать" использование хэш-индекса при использовании B-Tree, создав другой столбец и сохраняя хэш большого значения на нем. Скажем, вы храните URL-адрес в поле, и значения довольно велики. Вы также можете создать целое поле с именем url_hash
и использовать хеш-функцию типа CRC32
или любую другую хэш-функцию для хэширования URL-адреса при его вставке. И затем, когда вам нужно запросить это значение, вы можете сделать что-то вроде этого:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
Проблема с приведенным выше примером заключается в том, что поскольку функция CRC32
генерирует довольно небольшой хеш, вы получите много столкновений в хешированных значениях. Если вам нужны точные значения, вы можете исправить эту проблему, выполнив следующие действия:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
По-прежнему стоит хэш-вещи, даже если число столкновений является большим, потому что вы будете выполнять только второе сравнение (строка) против повторяющихся хэшей.
К сожалению, используя этот метод, вам все равно нужно попасть в таблицу, чтобы сравнить поле url
.
Обернуть
Некоторые факты, которые вы можете учитывать каждый раз, когда хотите поговорить об оптимизации:
-
Целочисленное сравнение выполняется быстрее, чем сравнение строк. Это можно проиллюстрировать на примере эмуляции хэш-индекса в InnoDB
.
-
Возможно, добавление дополнительных шагов в процесс делает его быстрее, а не медленнее. Это можно проиллюстрировать тем фактом, что вы можете оптимизировать SELECT
, разделив его на два шага, сделав первые значения хранилища во вновь созданной таблице в памяти, а затем выполните более тяжелые запросы в этой второй таблице.
У MySQL есть и другие индексы, но я думаю, что B + Tree один из самых используемых когда-либо, а хэш - хорошая вещь, но вы можете найти другие в Документация по MySQL.
Я настоятельно рекомендую вам прочитать книгу "Высокая производительность MySQL", ответ выше определенно основывался на ее главе об индексах.
Ответ 3
Что такое индекс?
Итак, что такое индекс? Ну, индекс - это структура данных (чаще всего это B-дерево), которая хранит значения для определенного столбца в таблице. Индекс создается в столбце таблицы. Итак, ключевыми моментами, которые следует помнить, является то, что индекс состоит из значений столбцов из одной таблицы и что эти значения хранятся в структуре данных. Индекс - это структура данных - помните об этом.
Давайте начнем наш учебник и объясним, почему вам нужен индекс базы данных, пройдя очень простой пример. Предположим, что we have a database table called Employee with three columns – Employee_Name, Employee_Age, and Employee_Address
. Предположим, что таблица Employee имеет тысячи строк.
Теперь скажем, что мы хотим запустить запрос в find all the details of any employees who are named ‘Jesus’?
Итак, мы решили запустить простой запрос, например:
SELECT * FROM Employee
WHERE Employee_Name = 'Jesus'
Что произойдет без индекса в таблице?
Как только мы запустим этот запрос, what exactly goes on behind the scenes to find employees who are named Jesus? Well, the database software would literally have to look at every single row in the Employee table to see if the Employee_Name for that row is ‘Jesus’.
И, поскольку нам нужна каждая строка с именем "Иисус внутри", мы не можем просто перестать смотреть, как только найдем только одну строку с именем "Иисус", потому что могут быть другие ряды с именем Иисус. Таким образом, каждая строка до последней строки должна быть найдена` - что означает, что тысячи строк в этом сценарии должны быть проверены базой данных, чтобы найти строки с именем "Иисус". Это то, что называется полным сканированием таблицы.
Как индекс базы данных может помочь производительности
Возможно, вы думаете, что полное сканирование таблицы неэффективно для чего-то такого простого - не должно ли программное обеспечение быть умнее? Почти как смотреть весь стол с человеческим глазом - очень медленно и вовсе не гладкий. Но, как вы, вероятно, догадались по названию эта статья, вот где индексы могут многое помочь. Целый точка с индексом - ускорить поисковые запросы по существу сокращая количество записей/строк в таблице, которые должны быть рассмотрено.
Какая структура данных является индексом?
B-деревья - наиболее часто используемые структуры данных для индексов. Причина, по которой B-деревья являются самой популярной структурой данных для индексов, объясняется тем, что они эффективны во времени - поскольку поиск, удаление и вставки могут выполняться в логарифмическом времени. И еще одна важная причина, по которой B-деревья чаще используются, заключается в том, что данные, которые хранятся внутри B-дерева, могут быть отсортированы. СУРБД обычно определяет, какая структура данных фактически используется для индекса. Но в некоторых сценариях с определенными СУБД вы можете указать, какую структуру данных вы хотите использовать в своей базе данных при создании самого индекса.
Как индекс повышает производительность?
Поскольку индекс представляет собой структуру данных, которая используется для хранения значений столбцов, поиск этих значений становится намного быстрее. И, если индекс использует наиболее часто используемый тип структуры данных - B-дерево, то структура данных также сортируется. Значение сортировки столбцов может быть важным улучшением производительности - читайте дальше, чтобы узнать, почему.
Предположим, что мы создаем индекс B-дерева в столбце Employee_Name. Это означает, что при поиске сотрудников с именем "Иисус" с использованием SQL, который мы показали ранее, тогда всю таблицу Employee не нужно искать, чтобы найти сотрудников с именем "Иисус" ". Вместо этого база данных будет использовать индекс для поиска сотрудников по имени Иисус, потому что индекс, по-видимому, будет отсортирован по алфавиту по имени сотрудников. И, поскольку он отсортирован, это означает, что поиск имени намного быстрее, потому что все имена, начинающиеся с" J", будут рядом друг с другом в индексе! Важно также отметить, что индекс также хранит указатели на строку таблицы, чтобы можно было получить другие значения столбцов - читайте для получения дополнительной информации об этом.
Как создать индекс в SQL:
Вот как выглядит фактический SQL, чтобы создать индекс в столбце Employee_Name из нашего примера раньше:
CREATE INDEX name_index
ON Employee (Employee_Name)
Как создать индекс с несколькими столбцами в SQL:
Мы также могли бы создать индекс в двух столбцах таблицы Employee, как показано в этом SQL:
CREATE INDEX name_index
ON Employee (Employee_Name, Employee_Age)
Ответ 4
В основном индекс представляет собой карту всех ваших ключей, отсортированных по порядку. Со списком в порядке, то вместо проверки каждого ключа он может сделать что-то вроде этого:
1: Идите в середину списка - выше или ниже того, что я ищу?
2: Если выше, перейдите к промежуточной точке между серединой и дном, если нижний, средний и верхний
3: выше или ниже? Снова перейдите к средней точке и т.д.
Используя эту логику, вы можете найти элемент в отсортированном списке примерно за 7 шагов вместо проверки каждого элемента.
Очевидно, что есть сложности, но это дает вам основную идею.
Ответ 5
Индекс базы данных или просто индекс помогает ускорить извлечение данных из таблиц. Когда вы запрашиваете данные из таблицы, сначала MySQL проверяет, существуют ли индексы, тогда MySQL использует индексы для выбора точных физических соответствующих строк таблицы вместо сканирования всей таблицы.
Индекс базы данных аналогичен индексу книги. Если вы хотите найти тему, сначала посмотрите вверх по индексу, а затем откройте страницу, в которой есть тема, не просматривая всю книгу.
Настоятельно рекомендуется создать индекс в столбцах таблицы, из которых вы часто запрашиваете данные. Обратите внимание, что все столбцы первичного ключа автоматически помещаются в основной индекс таблицы.
Если индекс помогает ускорить данные запроса, почему мы не используем индексы для всех столбцов? Если вы создаете индекс для каждого столбца, MySQL должен строить и поддерживать индексную таблицу. Всякий раз, когда изменения записываются в таблицу таблицы, MySQL должен перестроить индекс, что требует времени, а также снижает производительность сервера базы данных.
Создание индекса MySQL
Вы часто создаете индексы при создании таблиц. MySQL автоматически добавляет в индекс любой столбец, который объявляется как PRIMARY KEY, KEY, UNIQUE или INDEX. Кроме того, вы можете добавлять индексы в таблицы, у которых уже есть данные.
Чтобы создать индексы, вы используете оператор CREATE INDEX. Ниже приведен синтаксис оператора CREATE INDEX:
1
2
3
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name USING [BTREE | HASH | RTREE] ON table_name (column_name [(length)] [ASC | DESC],...)
Сначала вы указываете индекс на основе типа таблицы или хранилища:
UNIQUE означает, что MySQL создаст ограничение, что все значения в индексе должны быть уникальными. Дублирующее значение NULL разрешено во всех механизмах хранения, кроме BDB. Индекс FULLTEXT поддерживается только механизмом хранения MyISAM и принимается только в столбце с типом данных CHAR, VARCHAR или TEXT. Индекс SPATIAL поддерживает пространственный столбец и доступен для механизма хранения MyISAM. Кроме того, значение столбца не должно быть NULL.
Затем вы указываете индекс и его тип после ключевого слова USING, такого как BTREE, HASH или RTREE, также на основе механизма хранения таблицы.
Ниже приведены механизмы хранения таблицы с соответствующими разрешенными типами индексов:
Поддерживаемые типы индексов хранения
MyISAM BTREE, RTREE
InnoDB BTREE
ПАМЯТЬ /HEAP HASH, BTREE
NDB HASH
В-третьих, вы объявляете имя таблицы и столбцы списка, которые хотите добавить в индекс.
Пример создания индекса в MySQL
В базе данных примеров вы можете добавить столбец OfficeCode таблицы employee в индекс с помощью инструкции CREATE INDEX следующим образом:
1
CREATE INDEX officeCode ON employees(officeCode)
Удаление индексов
Помимо создания индекса, вы также можете удалить индекс, используя оператор DROP INDEX. Интересно, что оператор DROP INDEX также сопоставляется с выражением ALTER TABLE. Ниже приведен синтаксис удаления индекса:
1
DROP INDEX index_name ON table_name
Например, если вы хотите удалить индекс OfficeCode таблицы employee, который мы создали выше, вы можете выполнить следующий запрос:
1
DROP INDEX officeCode ON employees
Ответ 6
Взгляните на эту ссылку: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
Как они работают, слишком обширна тема для покрытия в одном сообщении SO.
Здесь - одно из лучших объяснений индексов, которые я видел. К сожалению, это для SQL Server, а не для MySQL. Я не уверен, насколько похожи эти два...
Ответ 7
Возьмите это видео для более подробной информации об индексировании
Простая индексация
Вы можете создать уникальный индекс в таблице. Уникальный индекс означает, что две строки не могут иметь одинаковое значение индекса. Вот синтаксис для создания индекса в таблице
CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);
Вы можете использовать один или несколько столбцов для создания индекса. Например, мы можем создать индекс на tutorials_tbl
с помощью tutorial_author.
CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)
Вы можете создать простой индекс в таблице. Просто опустите ключевое слово UNIQUE из запроса, чтобы создать простой индекс. Простой индекс позволяет дублировать значения в таблице.
Если вы хотите индексировать значения в столбце в порядке убывания, вы можете добавить зарезервированное слово DESC после имени столбца.
mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)
Ответ 8
Я хочу добавить свои 2 цента. Я далек от того, чтобы быть экспертом по базам данных, но недавно я немного прочитал эту тему; достаточно для меня, чтобы попытаться дать ELI5. Таким образом, здесь может объяснение дилетанта.
Я так понимаю, что индекс подобен мини-зеркалу вашей таблицы, почти как ассоциативный массив. Если вы передадите ему соответствующий ключ, вы можете просто перейти к этой строке в одной "команде".
Но если у вас не было этого индекса/массива, интерпретатор запросов должен использовать цикл for, чтобы пройти по всем строкам и проверить совпадение (сканирование полной таблицы).
Наличие индекса имеет "обратную сторону" дополнительного хранилища (для этого мини-зеркала) в обмен на "обратную сторону" поиска контента быстрее.
Обратите внимание, что (в зависимости от вашего движка БД) создание первичных, внешних или уникальных ключей автоматически устанавливает соответствующий индекс. Тот же принцип в основном, почему и как эти ключи работают.
Ответ 9
Добавление визуального представления в список ответов.
MySQL использует дополнительный уровень косвенности: записи вторичного индекса указывают на записи первичного индекса, а сам первичный индекс содержит расположения строк на диске. Если смещение строки изменяется, необходимо обновить только основной индекс.
Предупреждение: структура данных диска выглядит плоской на диаграмме, но на самом деле
B+ дерево.
Источник: ссылка
Ответ 10
В MySQL InnoDB есть два типа индекса.
Первичный ключ, который называется кластеризованным индексом. Ключевые слова индекса хранятся с
реальные данные записи в листовом узле B + Tree.
Вторичный ключ, который не является кластеризованным индексом. Эти индексы хранят только ключевые слова первичного ключа вместе со своими собственными ключевыми словами индекса в листовом узле B + Tree. Поэтому при поиске по вторичному индексу он сначала находит ключевые слова индекса первичного ключа и сканирует первичный ключ B + Tree, чтобы найти записи реальных данных. Это замедлит вторичный индекс по сравнению с поиском первичного индекса. Однако, если все столбцы select
находятся во вторичном индексе, нет необходимости снова искать первичный индекс B + Tree. Это называется индексом покрытия.