Comments 14
Всегда пожалуйста.
Насчет ltree: это ж все-таки не индекс, а тип данных. Или имеется в виду индексирование этого типа?
Не совсем. Если в индексной странице не осталось ни одного элемента, логически она удаляется из индекса. Это происходит не сразу (чтобы не сломать другие процессы, работающие с индексом в то же самое время), но происходит — этим занимается очистка (vacuum).
Логически — в том смысле, что на эту страницу не будет ссылок из других индексных страниц; при обходе дерева мы в нее не попадем. Но физически размер файла при этом не меняется, просто в середине образуется «дыра», которая может быть использована для новых элементов.
Вот что не происходит, так это объединения двух недозаполненных страниц. То есть при ну очень-очень неудачном раскладе теоретически можно вместо сильно ветвистого дерева получить совсем даже не ветвистое. Если задаться целью специально построить такой пример, то надо сначала вставить в таблицу много-много строк, а затем удалить из таблицы почти все, но так, чтобы на каждой индексной странице что-нибудь, да осталось.
А на крайний случай есть универсальная пилюля — полное перестроение индекса. Reindex (или vacuum full, что почти одно и то же), либо неблокирующее создание нового индекса с последующим удалением старого (create index concurrently), либо утилиты типа pg_repack или pg_squeeze.
При этом, перестроение индекса надо всегда вручную делать? Никаких автоматических средств для этого нет, то есть надо самостоятельно мониторить, что индексы не стали огромными?
А у меня что-то получается, что при удалении строк страницы индекса не освобождаются.
![](https://habrastorage.org/getpro/habr/upload_files/0e2/13a/5c5/0e213a5c5b3a0d03657e627b11649c0d.png)
Я создал таблицу, у которой единственный индекс - 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 его не поменяет. Можно только создать другой индекс.
Индексы в PostgreSQL — 4