Как будет повторно использоваться пространство после освобождения идентификатора элемента в PostgreSQL?

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

После использования Vacuum, идентификатор элемента и данные элемента мертвых кортежей будут удалены. Если идентификатор удаленного элемента находится посреди других идентификаторов, между идентификаторами будет разрыв. Поскольку обычно новые идентификаторы добавляются в начало свободного пространства, будет ли это освобожденное пространство между ними когда-либо повторно использоваться? Если да, то как мы можем найти это место?

Вот наглядный пример этого сценария:

страница после вакуума

После удаления некоторого кортежа между (0,3) и (0,5) осталось неиспользуемое пространство. Как это пространство будет снова использовано повторно? Благодаря!

3 ответа

Решение

Технический термин PostgreSQL для того, что вы называете "идентификатором элемента", - "указатель строки". "Указатель элемента" или "идентификатор кортежа" представляет собой комбинацию номера страницы и указателя строки ((0,5) в вашем изображении).

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

Указатели строк образуют массив после заголовка страницы. Когда в буфер нужно добавить новый кортеж, можно использовать любой указатель на свободную строку. Если указателя свободной строки нет, в конец массива добавляется указатель новой строки. Для справки см. PageAddItemExtended в src/backend/storage/page/bufpage.c.

Массив указателей строк никогда не сжимается, если страница не усекается и не добавляется позже. Неиспользуемые слоты массива будут повторно использоваться по мере добавления новых кортежей. Если страница когда-то была заполнена большим количеством небольших кортежей, а затем была удалена и повторно заполнена небольшим количеством больших кортежей, будет лишний неиспользованный lp, занимающий небольшой объем места, который никогда не будет использоваться повторно.

Вы можете использовать heap_page_items из pageinspect с where lp_off=0 найти их.

Предположим, что таблица содержит 2 страницы. Мы смотрим на первую страницу (0-я страница). Предположим, что здесь вставлены некоторые данные, а на странице есть три кортежа (строки). Теперь, если, скажем, мы удаляем кортеж 2, тогда PG удаляет кортеж номер 2 и переупорядочивает оставшиеся кортежи для дефрагментации, а затем обновляет как FSM, так и виртуальную машину этой страницы. PostgreSQL продолжает этот процесс до последней страницы (вакуума).

Когда вы делаете вакуум, ненужные указатели строк не удаляются, и они будут повторно использоваться в будущем.

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

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