Механизм Heap only tuples в PostgreSQL

Автор оригинала: Michael Malis
  • Перевод

Postgresql отличается от других СУБД тем, что в ней при операции UPDATE, изменений в существующей строке не происходит, а вместо этого делается копия строки, которая отличается от оригинала значениями колонок, затронутых апдейтом — в оригинале они старые, а в копии — изменённые. Этот подход с одной стороны позволяет избежать блокировок при одновременном выполнении запросов на чтение и запись а с другой стороны порождает необходимость постоянно вычищать старые версии строк, которые уже никто и никогда не прочитает. В связи с этой архитектурной фичей нередко возникает вопрос, что будет, если нужно хранить в БД что-то вроде времени последнего доступа к данным, которые в остальном не меняются. Не отзовётся ли это на производительности? Не приведёт ли к постоянной перестройке индексов?


Если коротко, то да, Copy On Write никуда не денется, но индексы во многих случаях можно будет не перестраивать, благодаря HOT.


Heap only tuples, также известные как HOT это оптимизация которую использует Postgres для того, чтобы уменьшить количество I/O необходимого для апдейтов. Из-за MVCC апдейт в Постгресе состоит из поиска строки для апдейта и вставки новых версий строки в базу данных. Основной недостаток этой процедуры — нужда в повторном добавлении строки в каждый индекс.
Это требует намного больше I/O потому что строку нужно повторно вставить в каждый индекс в таблице. Необходимость в повторной вставке возникает потому что физическое положение новой версии строки на диске отличается от физического положения старой версии.


Чтобы уменьшить количество I/O необходимого для UPDATE, команда Постгрес добавила в Постгрес HOT. Идея, стоящая за HOT относительно проста. При апдейте строки, если это возможно, Постгрес поставит новую копию строки сразу после старой копии строки. Плюс в старой копии строки проставляется специальная метка, для того чтобы Постгрес знал, что новая копия строки находится сразу после старой. Поэтому обновлять все индексы не нужно.


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


Сейчас HOT задействован только тогда, когда в апдейте участвуют только не индексируемые столбцы. Если хотя бы один столбец, участвующий в апдейте входит в индекс, HOT применить нельзя. В этом случае с применением HOT есть несколько проблем. Например, когда по индексу на колонке, которую проапдейтили нужно сделать индекс скан и старая копия строки попадает в предикат скана, а новая — нет. В этой ситуации, Постгрес попробует использовать индекс, чтобы быстро найти все строки, которые подходят для предиката запроса, и в случае столбцов, которые проапдейтили с помощью HOT, выдаст новую копию строки, которая предикату запроса не подходит. Благодаря этому ограничению (что HOT не работает когда в апдейт включены индексируемые колонки), Постгрес может дать гарантию, что когда он пытается найти строки, которые подходят для предиката, через который пропускают индекс, то если предикату подходит старая версия строки, то новая версия строки ему тоже подходит и наоборот.


В данный момент в разработке находится насширение HOT под названием WARM, которое работает и при апдейте столбцов, на которых созданы индексы. Идея за WARM в том, чтобы ставить новую строку сразу за старой и обновлять строку для индексов, в которых были изменённые столбцы. Это значительно осложняет описанную ситуацию, потому что теперь Постгресу нужен способ каким-то образом определить проходит ли строка фильтр для индекса, или нет.


P. S. В оригинальной статье описан механизм HOT, но тут имеется в виду механизм, в котором задействованы heap only tuples, а у самого термина есть отдельное значение.


Heap only tuple это как раз новая версия строки. Heap — это как ни странно — таблица, а Heap only означает, что эту строку можно найти только по цепочке, которая ведёт от старшей версии строки, которая называется корневой.

Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 2

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

    Что будет, если в процессе автовакуума будет удалена старая версия строки?
      0

      Старая версия строки будет удалена не полностью. Та часть, которая указывает на новую версию строки останется целой.


      Теперь немного подробнее.


      Строка в постгресе состоит из двух частей — указателя на то, где находится строка и самой строки. Индекс ссылается именно на указатель.


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


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


      Вот так оно происходит, если сократить и упростить.

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое