digital-garden/source/доклады/Доклад. Индексы в PostgreSQL. Как понять, что создавать.md

8.5 KiB
Raw Blame History

parents author zero-link link
Java конференция Joker
Индекс в PostgreSQL
Сальников Андрей (Data Egret)
00 Базы Данных
https://www.youtube.com/watch?v=ju9F8OvnL4E

О чем доклад

  • Говорится в основном о OLTP нагрузке, про OLAP не будем
  • Объемы баз данных от 20Гб до 10Тб

Заметки

  • PostgreSQL: Documentation: 16: CREATE INDEX
  • Для первичного ключа индекс создается автоматически
  • Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит.
  • Плюсы индексов
    • Ускорение запросов
  • Минусы
    • Замедление записи в таблицы (80% к 20%). Так как необходимо будет перестраивать индекс при вставке новых значений.
    • Дополнительные объемы дискового пространства. Размер индекса в половину размера таблицы считается нормальным и оптимальным
    • Усложненное технического обслуживание.
      • #todo bloat. индексы пухнуть и переодически их нужно пересоздавать
  • Перед созданием индекса стоит провести предварительный анализ. Так как не все индексы полезны, некоторые индексы могут ухудшить ситуацию.
  • Что нужно для создания индекса?
    • Ориентироваться только на продуктовое окружение, так как тестовые окружения не соответствуют реальности.
    • Собрать статистику нагрузки на БД от запросов.
      • Инструменты для сбора статистики:
        • pg_stat_statements - отличный инструмент
        • pgBadger - использовать с осторожностью. Собирает статистику из логов postgres. Но в логи попадают не все запросы.
    • Иметь примеры запросов с параметрами.
      • Для понимания входящих параметров запроса.
      • Необходимо для проверки оптимизаций
    • Уметь читать статистику распределения данных (планировщик).
    • Представление pg_stats.
    • Вручную собрать более полную статистику.
      • По умолчанию PostgrteSQL использует для сбора статистики только 30k строк из таблицы. Из-за этого статистика может расходиться с реальностью.
  • Типы индексов
    • btree
      • Наиболее распространенный тип индексов
      • Очень хороший алгоритм работы
      • Покрывает 90% задач
      • Легко создать ориентируясь на статистику по таблице
      • Обслуживает как операции сравнения так и операции равенства
      • Позволяет выполнить сортировку
    • hash индекс
      • Абсолютно бесполезен. Используйте btree.
      • Занимает меньше места на диске, чем btree
      • Обслуживает только операции равенства.
      • Нельзя выполнить сортировку
    • gist индекс
      • В чистом виде полезен для гео-данных
      • Расширения
        • pg_trgm - like, ilike, ~, ~* (regexp)
        • btree_gits - слодные constrains с интервалами. Позволяет переложить на базу данных задачу по контролю пересечения времени. Например, если нужно создать расписание, и чтобы временные интервалы заданий не пересекались.
    • sp_gist индекс
      • Нет практических применений в OLTP
      • Возможно полезен в научной сфере
    • gin индекс
      • Может сильно ухудшить время вставки в таблицу
      • Хорошо для текстового поиска
      • Позволяет ускорить поиск по jsonb
        • jsonb_ops - используется по умолчанию. Индексирует все значения jsonb, из-за этого индекс получается больших размеров.
        • json_path_ops - заточен на поиск путей в json. То есть позволяет ответить, есть ли такое-то поле в jsonb или его нет.
    • brin
      • Компактный индекс
      • Подходит для упорядоченных данных

Практика

  • Индекс по первичному ключу занял 1/4 от размера таблицы
  • Таблица ссылается сама на себя, но это сделано для удобства доклада. Те же самые выводы распространятся и на связи с другими таблицами.

Удаляем строку

600

  • В удалении задействован первичный ключ, поэтому используется поиск по индексу
  • ==Самый долгий этап это проверка связей с таблицей==

Под капотом для поиска внешних связей мы используем полное сканирование таблицы (Seq Scan). 600

==Вывод: не забывать создавать индексы на Foreign Key.==

Добавляем индекс на FK и проверяем результат: 600 Мы получили ускорение в 2055 раз.

Смотрим статистику

Таблица статистик pg_stats 600 В данном случае у нас 92% значений в колонке это null значения.

Основываясь на этой информации мы можем уменьшить размер индекса. Для этого изменим запрос на создание индекса, добавив where fk_id is not null. 600

Таким образом у нас получилось сжать индекс в 14 раз: 500

Поиск записей по статусу

Мы находим записи по какому-то статусу. 300 600

Часто появляется желание сделать индекс по полю статуса: 600 По факту мы индексируем поле, которое имеет небольшую селективность. Такой индекс не эффективный.

Хороший вариант в данном случае: 600

Почти идеальный: 600

500