digital-garden/dev/database/Индекс базы данных.md

76 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
aliases:
- индексов
- индекс
- индексы
- индексирования
- индекса
tags:
- maturity/🌱
date: 2024-10-11
---
**Индекс** — это служебная структура данных, которая позволяет ускорить операции поиска, сортировки и фильтрации данных в реляционных базах данных. Индексы создаются для одного или нескольких столбцов таблицы, с целью [[Оптимизация SQL запросов|ускорения выполнения запросов к базе данных]].
Индексы обычно реализуются на основе различных структур данных, каждая из которых подходит для определённых типов запросов. Наиболее распространённые структуры данных для индексов:
- **B-деревья** ([[../fundamental/structure/B-tree|B-tree]]). Широко применяются для ускорения операций поиска, сортировки и диапазонных запросов.
- **Хэш-индексы.** Хорошо подходят для поиска по точным значениям, но неэффективны для диапазонных запросов.
- **GiST и R-деревья.** Используются для индексации пространственных данных, таких как координаты или географические объекты.
СУБД автоматически выбирает наиболее подходящий индекс для выполнения запроса. Важно следить за тем, чтобы индекс покрывал нужные столбцы и типы запросов, так как ==неправильный выбор индекса может замедлить выполнение запросов.==
**Польза:**
- **Ускорение запросов.** Индексы значительно ускоряют выполнение запросов, особенно для операций равенства, сравнений и сортировки данных.
-ример_: `SELECT * FROM employees WHERE department = 'HR';` — индекс на столбце `department` ускорит выполнение этого запроса.
- **Покрытие запросов.** В некоторых случаях индексы могут содержать все данные, необходимые для выполнения запроса, что позволяет избежать чтения самих строк таблицы (так называемый "[[Покрывающий индекс]]").
-ример_: `SELECT name, age FROM employees WHERE department = 'IT';` — если индекс покрывает столбцы `name`, `age` и `department`, то чтение строк таблицы не потребуется.
- **Поддержка ограничений.** Индексы могут использоваться для реализации ограничений на уникальность данных (UNIQUE), а также для обеспечения ссылочной целостности (FOREIGN KEY).
**Накладные расходы:**
- **Влияние на производительность**: добавление индексов замедляет операции вставки, обновления и удаления, так как индекс должен быть обновлен при каждой модификации данных. При создании индексов необходимо учитывать характер нагрузки на таблицу, особенно если часто выполняются операции записи. Например, при [[Online Transaction Processing|OLTP]] нагрузке чтение данных значительно преобладает над записью (80% чтения и 20% записи), что оправдывает использование индексов.
- **Блокировка таблицы**: добавление индекса блокирует таблицу, что может негативно сказаться на производительности, особенно в [[../../meta/zero/00 HighLoad|высоконагруженных системах]].
- **Дополнительное использование дискового пространства.** Индексы требуют значительного объема дискового пространства для хранения. Обычно объем индексов составляет около половины размера таблицы. Если размер индексов превышает размер таблицы, это может указывать на необходимость оптимизации.
- **Необходимость технического обслуживания.** Со временем индексы могут фрагментироваться и требовать пересоздания для поддержания эффективности. В некоторых системах управления базами данных (СУБД) это может происходить автоматически, однако в других случаях требуется ручное вмешательство.
**Частые ошибки:**
- **Низкая селективность.**: индексы на колонках с низкой [[Селективность колонки|селективностью]] могут оказаться неэффективными и не принести ожидаемого увеличения производительности.
- Индекс на столбце `gender` с двумя возможными значениями (`M`, `F`) не даст значительного выигрыша в производительности.
- **Неиспользуемые индексы**. Индексы, которые не используются, создают дополнительные накладные расходы на хранение и обслуживание. Рекомендуется периодически проверять активность индексов и удалять те, что не используются. Найти такие индексы поможет [[postgresql/pageinspect|pageinspect]].
- **Высокие накладные расходы.** В некоторых случаях затраты на обновление индексов могут превышать выгоды от их использования. Наличие большого количества индексов на одной таблице может вызвать накладные расходы и ухудшить производительность, особенно при частых изменениях данных.
**Когда индексы не работают:**
- **Использование вычисляемых выражений.** Например, выражение `WHERE column + 1 = 10` не будет эффективно использовать индекс. В таких случаях могут применяться специальные методы, такие как индексы по выражению или генерация вычисляемых колонок.
-ример_: Для выражения `column + 1` можно создать вычисляемый столбец и индексировать его.
- **Обработка большого количества записей.** Если запрос возвращает слишком много строк, использование индекса может быть неэффективным.
- **Агрегатные функции.** Лишь некоторые агрегатные функции, такие как `MIN()` и `MAX()`, могут эффективно использовать индексы.
- **Логические операторы.** Индексы хорошо работают с условиями, использующими логический оператор И (`AND`), но менее эффективны с логическим ИЛИ (`OR`):
- **Логические операторы.** Индексы хорошо работают с условиями, использующими логический оператор И (`AND`), но менее эффективны с логическим ИЛИ (`OR`).
-ример запроса с ИЛИ_: `SELECT * FROM tb WHERE a = 0 OR b = 0;` — в этом случае индексы для каждого столбца могут быть использованы независимо (индексы на `a` и `b`), но составной индекс по этим столбцам не будет работать эффективно.
**Какие бывают индексы?**
- **Уникальные и неуникальные.** Уникальные индексы обеспечивают уникальность значений в столбцах. Неуникальные индексы допускают повторяющиеся значения.
- **Простые и составные.** Простые индексы создаются для одного столбца, а [[Составной индекс в БД|составные]] — для нескольких столбцов.
- **Кластерные и некластерные.** Кластерные индексы определяют физическое расположение данных на диске, а некластерные индексы хранят указатели на строки таблицы.
**Реализации:**
- [[postgresql/Индекс в PostgreSQL|Индекс в PostgreSQL]]
- [[../../../../_inbox/Индекс в MySQL|Индекс в MySQL]]
***
## Мета информация
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-10-11]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Индекс в MySQL]]
- [[Индекс в PostgreSQL]]
- [[Покрывающий индекс]]
- [[Составной индекс в БД]]
<!-- SerializedQuery END -->