Физическая структура индекса PostgreSQL

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

1 ответ

Индексы B-дерева - технология десятилетней давности, поэтому веб-поиск найдет много хороших подробных описаний. В двух словах:

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

Это эскиз индекса с глубиной три, но помните следующее:

  • некоторые узлы опущены, в действительности все конечные узлы находятся на уровне 3
  • на самом деле здесь не три записи (ключи) в одном узле, а около 100

                                     ┌───────────┐
                level 1 (root node)  │ 20 75 100 │
                                     └───────────┘
                                   ╱    ╱   │     ╲
                                  ╱    ╱    │      ╲
                                 ╱    ╱     │       ╲
                    ┌───────────┐┌─────┐┌──────────┐┌─────┐
           level 2  │ 5  10  15 ││ ... ││ 80 87 95 ││ ... │
                    └───────────┘└─────┘└──────────┘└─────┘
                                       ╱   ╱   │    ╲
                                      ╱   ╱    │     ╲
                                     ╱   ╱     │      ╲
                             ┌─────┐┌─────┐┌──────────┐┌─────┐
        level 3 (leaf nodes) │ ... ││ ... ││ 89 91 92 ││ ... │
                             └─────┘└─────┘└──────────┘└─────┘

Некоторые заметки:

  • Указатели на следующий уровень фактически находятся в промежутках между записями, поиск в индексе подобен "детализации" до правильной конечной страницы.
  • Каждый узел также связан со своими братьями и сестрами, чтобы облегчить вставку и удаление узлов.
  • Когда узел заполнен, он разделяется на два новых узла. Это расщепление может повторяться и даже достигать корневого узла. Когда корневой узел разделен, глубина индекса увеличивается на 1.
  • В реальной жизни глубина индекса B-дерева едва ли может превышать 5.
  • При удалении записи индекса остается пустое место. Существуют методы, позволяющие объединить это путем объединения страниц, но это сложно, и PostgreSQL этого не делает.

Теперь к вашему вопросу:

Когда запись таблицы (кучи) удаляется VACUUM поскольку он не виден ни для какого активного снимка, соответствующая запись в индексе также удаляется. Это приводит к пустому пространству в индексе, которое может быть использовано в будущих записях индекса.

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

Некоторое количество раздувания индекса (до 50%) является нормальным, но если необычные шаблоны использования, такие как массовые обновления и удаления, вызывают плохое раздувание индекса, вам придется переписать индекс с REINDEX, тем самым избавляясь от вздутия. К сожалению, эта операция блокирует индекс, поэтому весь параллельный доступ блокируется до тех пор, пока он не будет выполнен.

Другие вопросы по тегам