Что означает «индекс» в РСУБД? [закрыто]

21

Я использую индексы, как это делают большинство разработчиков (в основном на ... хорошо! Индексе), но я уверен, что есть много хитрых способов оптимизировать базу данных с помощью индекса. Я не уверен, является ли это специфическим для любой реализации СУБД.

Мой вопрос: каковы хорошие примеры того, как использовать индекс (за исключением базовых, очевидных случаев), и как СУБД оптимизирует свою базу данных, когда вы указываете индекс для таблицы?

Томас Жулин
источник
При дальнейшем рассмотрении этого вопроса этот вопрос слишком общий для данного сайта. Если мы изменим объем вопроса, который может быть уместным, в противном случае этот вопрос не подходит для сайта.
Jcolebrand
Мне нравится объяснять индексы, используя метафору библиотеки mysqlperformanceblog.com/2011/08/30/… Посмотрим, поможет ли это ..
Джонатан

Ответы:

11

Думайте об индексе как о «оглавлении» ... это упорядоченный список указателей на позиции в файле, то есть смещения. Скажем, у вас есть миллионы записей, хранящихся в таблице, вместо того, чтобы искать в таблице критерии соответствия, гораздо быстрее ссылаться на упорядоченный список совпадений, а затем складывать указатели на конкретные совпадающие строки. Прекрасным примером индекса является поле первичного ключа таблицы, чаще всего его поле «id». Если вам нужен идентификатор строки # 11234566, гораздо быстрее запросить указатель на указатель на данные, чем сканировать источник данных на предмет позиции 11234566.

Вот не столь очевидное использование индексации:

CREATE TABLE activity_log (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
activity_type_id SMALLINT UNSIGNED NOT NULL,
datetime_created DATETIME
KEY(activity_type_id),
PRIMARY KEY(id)
);
CREATE TABLE activity_log_to_date_key (
activity_log_id INT UNSIGNED NOT NULL,
date_created_key  INT UNSIGNED NOT NULL REFERENCES dim_datetime(id),
UNIQUE KEY(activity_log_id),
KEY(date_created_key)
);
CREATE TABLE dim_datetime (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
date_hour DATETIME NOT NULL,
PRIMARY KEY(id),
KEY(date_hour)
);

Ваша операция может создать вашу запись в журнале, но затем создать ссылку на индексированное время, которое будет быстрее искать / сортировать, чем ваша таблица журнала. Затем присоедините свою таблицу журналов по своему первичному ключу. Если вам нужно, чтобы я подробно остановился на этом, дайте мне знать. Я надеюсь это имеет смысл.

Пример запроса:

SELECT a.activity_log_id, al.activity_type_id, al.datetime_created
FROM activity_log_to_date_key a 
INNER JOIN dim_datetime d ON (d.id = a.date_created_key)
LEFT JOIN activity_log al ON (al.id = a.activity_log_id)
WHERE d.date_hour BETWEEN '2009-01-01 00:00:00' AND '2009-06-01 12:00:00';
randomx
источник
спасибо, это очень понятно! В вашем примере, «ПЕРВИЧНЫЙ» изменит способ, которым RDMBS хранит «смещение», или он просто используется для ограничений уникальности?
Томас Джулин
9

Одна вещь, которую многие люди упускают из виду, это то, что СУБД часто (или может только) использовать только один индекс на ссылку на таблицу в запросе, и если она может и использует несколько индексов, то, вероятно, будет быстрее использовать комбинированный индекс, если присутствует.

Например, при поиске строк WHERE AnIntegerColumn = 42 AND AnOtherInt = 69в большой таблице самым быстрым путем к этим строкам будет индекс по двум столбцам AnIntegerColumn и AnOtherInt. Если у вас есть только индекс по каждому по отдельности, но нет объединенного индекса, БД будет либо искать тот или другой индекс, и отдельно фильтровать результаты со вторым предложением, либо сканировать оба и объединять результаты впоследствии.

Еще одна распространенная простая операция, которую можно улучшить с помощью составных индексов, WHERE SomeColumn = <SomeValue> ORDER BY SomeOtherColumn- если есть индексы для SomeColumn и SomeOtherColumn (в правильном порядке), операции фильтрации и упорядочения могут выполняться одновременно при некоторых обстоятельствах.

Конечно, добавление слишком большого количества индексов может быть плохой оптимизацией, поскольку дополнительное пространство, используемое для хранения индексов (и нагрузка ввода-вывода для их поддержания, если ваша БД видит много операций записи), может быть более серьезной проблемой, чем чуть менее оптимальные запросы чтения. так что не переусердствуйте.

Дэвид Спиллетт
источник
2

Дэвид и Рэнди это покрыли. Я просто хотел добавить, что эта EXPLAINкоманда может очень помочь понять, когда вы получите большую экономию от создания индекса, а также предложить, какие индексы нужны. Он отобразит шаги, которые база данных предпринимает для выполнения вашего запроса, чтобы вы знали, какие биты занимают больше всего времени.

Gaurav
источник
Чтобы добавить ответ Гаурава, используйте «EXPLAIN EXTENDED», а затем сразу введите «SHOW WARNINGS», чтобы увидеть, как переводится ваш запрос.
randomx
1

Что-то, что я еще не упомянул здесь, это то, что когда у вас есть более одного диска, вы, вероятно, захотите поместить свой индекс на диск, отличный от того, где находятся данные. Это может ускорить некоторые операции. Я думаю, что это заслуживает вопроса само по себе, хотя.

jcolebrand
источник
Раньше это было правдой, но в наши дни мы говорим, не пытайтесь угадать вашу подсистему ввода-вывода. Вы все равно не знаете, где массив данных будет размещать ваши данные.
Гай
1
@gaius Я скорее имел в виду, если у вас не было настройки RAID5 (или подобной), чтобы поместить индексы в E:, данные в F: и т. д.
jcolebrand