Pull to refresh

Comments 14

Спасибо. Еще очень хотелось бы увидеть статью про 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 его не поменяет. Можно только создать другой индекс.

Sign up to leave a comment.