Обновить

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

Спасибо. Еще очень хотелось бы увидеть статью про ltree индексы.

Всегда пожалуйста.
Насчет ltree: это ж все-таки не индекс, а тип данных. Или имеется в виду индексирование этого типа?

Да, прошу прощения, неправильно выразился. Интересует именно тип данных ltree и способы его индексирования, плюсы и минусы, особенно при сравнительно большом количестве записей (десятки миллионов).

Ок, подумаю, но пока выглядит как отдельная тема, которую бы лучше раскрыл кто-нибудь с реальным опытом...

Поддержу за ltree
Правильно ли я понимаю, что при удалении всех данных из листового блока, он сам не удаляется из структуры индекса автоматически? Это может приводить к «перепробегам» при сканированию по индексу после массовых удалений из таблицы? И как эти проблемы решаются?

Не совсем. Если в индексной странице не осталось ни одного элемента, логически она удаляется из индекса. Это происходит не сразу (чтобы не сломать другие процессы, работающие с индексом в то же самое время), но происходит — этим занимается очистка (vacuum).
Логически — в том смысле, что на эту страницу не будет ссылок из других индексных страниц; при обходе дерева мы в нее не попадем. Но физически размер файла при этом не меняется, просто в середине образуется «дыра», которая может быть использована для новых элементов.


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


А на крайний случай есть универсальная пилюля — полное перестроение индекса. Reindex (или vacuum full, что почти одно и то же), либо неблокирующее создание нового индекса с последующим удалением старого (create index concurrently), либо утилиты типа pg_repack или pg_squeeze.

При этом, перестроение индекса надо всегда вручную делать? Никаких автоматических средств для этого нет, то есть надо самостоятельно мониторить, что индексы не стали огромными?

Да, это так.

беда - но видимо в реальной практике такое редко надо

Мониторинг - и будет автоматическое средство. Но не встроенное, да.

А у меня что-то получается, что при удалении строк страницы индекса не освобождаются.

Я создал таблицу, у которой единственный индекс - primary key (id). Вставил туда элементов, потом много раз сделал так: вставляю 10000 новых строк, потом удаляю 10000 строк с минимальными id. Размер индекса всё это время рос.

Потом я удалил всё из таблицы, запустил vacuum - индекс не уменьшился.

Потом для верности ещё сделал "vacuum (index_cleanup ON) ids;" - то же самое

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

Спасибо большое за интересные статьи и что продолжаете, как обещали.
Часть теории конечно вполне тривиальна, но здорово что всё вместе и последовательно.

Я хотел спросить на счёт порядка определения своего класса операторов. Скажем в вашем примере, сначала для комплексных чисел используется дефолтный метод. Что если мы сначала создадим btree индекс по этому полю, а потом уже определим класс операторов:
create operator class complex_ops

Достаточно ли postgres «умный» чтобы не стать использовать для индексов, создававшихся с другими операторами вновь созданный?

И если мы хотим чтобы старый индекс стал использовать новый класс операторов, его обязательно пересоздавать? Или есть другие возможности перестроения (REINDEX)?

Ой, что-то я оставил без ответа ваш вопрос, прошу прощения.
Индекс всегда строится с использованием какого-то одного класса операторов. Если мы построим индекс по полю типа complex, не определив свой класс операторов, то будет использован общий для составных типов класс record_ops:


t=# create type complex as (re float, im float);
CREATE TYPE
t=# create table numbers(x complex);
CREATE TABLE
t=# create index on numbers(x);
CREATE INDEX
t=# select opcname from pg_opclass where oid = (select indclass[0] from pg_index where indrelid = 'numbers'::regclass);
  opcname   
------------
 record_ops
(1 row)

Поменять класс операторов у индекса невозможно никак: он и сам по себе не изменится, и REINDEX его не поменяет. Можно только создать другой индекс.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
www.postgrespro.ru
Дата регистрации
Дата основания
Численность
501–1 000 человек
Местоположение
Россия
Представитель
Иван Панченко