digital-garden/_inbox/Индекс в PostgreSQL.md

10 KiB
Raw Blame History

aliases tags date zero-link parents linked
индексирования
зрелость/🌱
2024-03-31
00 PostgreSQL
Индексы в MySQL

Индекс это служебная структура данных, которая позволяет ускорить запросы (поиск, сортировку) к базе данных.

Польза:

  • Ускоряют запросы: равенство, сравнения, сортировка
  • В некоторых случаях позволяют избежать чтения из таблицы. Покрывающий индекс.
  • Через них можно делать constraints (UNIQUE, FOREIGN KEY)
  • Специальные оптимизации?

Накладные расходы:

  • Дополнительные объемы дискового пространства для хранения индекса. Размер индекса в половину размера таблицы считается нормальным и оптимальным
  • Обновляются при модификации данных, на что требуется время и ресурсы. Замедление записи в таблицы (80% к 20%). Так как необходимо будет перестраивать индекс при вставке новых значений.
  • Усложненное технического обслуживание. Индексы пухнут и переодически их нужно пересоздавать

Когда индексы не нужны?

  • Малая Селективность колонки.
  • Большие накладные расходы на поддержание индекса.
  • Когда индекс не используется вовсе.

Когда индексы не работают?

  • В условии используется вычисляемое выражение: WHERE counter + 1 = 46
  • Если будет отобрано слишком много записей.
  • Из агрегирующих функций только min() и max() получат ускорение.
  • Индексы хорошо работают с логическим И, и плохо работают с логическим ИЛИ.
    • SELECT * FROM tb WHERE a = 0 OR b = 0;
      • Можно использовать 2 индекса (а) и (b). Индекс (а, b) работать не будет.

Какие бывают индексы?

  • Не уникальные и уникальные. Уникальные без повторяющихся значений.
  • Простые и составные.
  • Кластерные и некластерные. Кластерные также хранят сами данные рядом с собой.

Типы индексов

  • btree
    • Основан на работе B-tree дерева
    • Наиболее распространенный тип индексов
    • Очень хороший алгоритм работы
    • Покрывает 90% задач
    • Легко создать ориентируясь на статистику по таблице
    • Обслуживает как операции сравнения так и операции равенства
    • Позволяет выполнить сортировку
  • hash индекс
    • Абсолютно бесполезен. Используйте btree.
    • Занимает меньше места на диске, чем btree.
    • Обслуживает только операции равенства.
    • Нельзя выполнить сортировку.
  • gist индекс
    • В чистом виде полезен для гео-данных. Например, поиск ближайшей гео-точки.
    • Расширения
      • pg_trgm - like, ilike, ~, ~* (regexp)
      • btree_gits - слодные constrains с интервалами. Позволяет переложить на базу данных задачу по контролю пересечения времени. Например, если нужно создать расписание, и чтобы временные интервалы заданий не пересекались.
  • sp_gist индекс
    • Нет практических применений в OLTP
    • Возможно полезен в научной сфере
  • gin индекс. Нужен тип данных tsvector
    • Может сильно ухудшить время вставки в таблицу
    • Хорошо для текстового поиска
    • Позволяет ускорить поиск по jsonb
      • jsonb_ops - используется по умолчанию. Индексирует все значения jsonb, из-за этого индекс получается больших размеров.
      • json_path_ops - заточен на поиск путей в json. То есть позволяет ответить, есть ли такое-то поле в jsonb или его нет.
  • brin
    • Компактный индекс
    • Подходит для упорядоченных данных

Создание индекса

Что нужно для создания индекса?

  • Ориентироваться только на продуктовое окружение, так как тестовые окружения не соответствуют реальности.
  • Собрать статистику нагрузки на БД от запросов.
    • Представление pg_stats.
    • Инструменты для сбора статистики:
      • pg_stat_statements - отличный инструмент
      • pgBadger - использовать с осторожностью. Собирает статистику из логов postgres. Но в логи попадают не все запросы.
  • Иметь примеры запросов с параметрами.
    • Для понимания входящих параметров запроса.
    • Необходимо для проверки оптимизаций
  • Вручную собрать более полную статистику. Редко делается, при необходимости.
    • По умолчанию PostgrteSQL использует для сбора статистики только 30k строк из таблицы. Из-за этого статистика может расходиться с реальностью.
  • Уметь читать статистику распределения данных (планировщик). explain

При создании индекса важно учитывать селективность колонки (разнообразие значений), чем она выше, тем лучше индекс будет выполнять свою задачу.

При добавлении индекса происходит блокировка таблицы.

Частичный индекс

Можно создать частичный индекс по условию, который будет покрывать только записи, которые удовлетворяют определенному условию where.

create index fk_not_null on pgconf(fk_id)
where fk id is not null;

Допустим, исключим из индекса по FK null значения. В этом случае мы не ускорим работу индекса, так как БД достаточно умная, чтобы делать это автоматически. Но это позволит уменьшить размер индекса. Но на больших данных это также может сказать и на производительности.

Заметки

  • Для первичного ключа индекс создается автоматически
  • Можно отключить автоматическое обновление индекса и сделать обновление ручным

Полезные команды

Расширение pageinspect позволяет изучить структуру индекса (размер страницы, количество страниц и так далее).

create extension pageinspect

Посмотреть сколько раз индекс использовался и когда был последний вызов.

select * from pg_stat_user_indexes

Посмотреть размер индекса

select pg_size_pretty(pg_indexes_size('orders'))

Проверить какие индексы существуют для таблицы:

select * from pg_indexes where tablename='table_name';

Можно получить мета информацию о дереве индекса:

select * from bt_metap('users_pkey');

Можно получить мета информацию о конкретном узле:

select * from bt_page_stats('users_pkey', 3);

Дополнительные материалы

Дополнительные заметки

Материалы: