October 16, 2008

В ожидании 8.4 - новый FSM (Free Space Map)

Перевод Waiting for 8.4 - new FSM (Free Space Map) с select * from depesz;

30го сентября Heikki Linnakangas применил свой патч, который вносит изменения в FSM:
Переписан FSM. Вместо того, чтобы полагаться на фиксированный (указанный) размер 
сегмента разделяемой памяти, информация о свободном месте теперь хранится в
отдельном FSM отношении для каждого отношения БД (за исключением hash индексов; они
не используют FSM).

Это устраняет необходимость в max_fsm_relations и max_fsm_pages GUC параметрах;
удалены все их вхождения в бэкэнд, initdb и документацию.

Переписан contrib/pg_freespacemap в соответствии с новой FSM реализацией. Так же
представлен новый вариант функции get_raw_page(regclass, int4, int4) в
contrib/pageinspect, который позволяет увидеть страницы любого отношения, и новая
функция fsm_page_contents() для проверки новых FSM страниц.
Что это значит для DBA?

Для начала, отпадает необходимость в настройке 2х параметров в postgresql.conf: max_fsm_pages и max_fsm_relations.

Эти параметры (когда установлены не корректно) могут сделать vacuum менее эффективным (что происходит очень часто). Т.ч., в основе, это хорошо, что их больше не будет.

Что ещё? Чтобы сделать это Haikki пришлось реализовать так называемые "дополнительные отношения" ("Relation forks"). И это важно, потому что (насколько я понимаю, если я понял не правильно, пожалуйста, поправьте меня) они могут (и наверняка будут) использоваться для хранения "карт видимости" ("visibility maps"), которые сделают vacuum более быстрым (и возможно повлияют на индексные сканирования, но это только моя догадка).

Что же это за "дополнительные отношения"? Всё просто. Как известно, таблицы хранятся в файлах следующим образом:
$PGDATA/base/<database-oid>/<table-filenode>
Иногда они имеют суфиксы .1, .2 и т.д. - в случае если размер таблицы (или индекса) превышеает гигабайт.

Дополнительные отношения добавляют второй набор файлов, именуемых:
<table-filenode>_1
Для FSM код "1" (но ходят разговоры о текстовых кодах).

Пример:
# create table x (id int4);
CREATE TABLE

# select oid from pg_database where datname = 'depesz';
oid
-------
16385
(1 row)

# select relfilenode from pg_class where relname = 'x' and relkind = 'r';
relfilenode
-------------
16387
(1 row)

=> ls -l $PGDATA/base/16385/16387*
-rw------- 1 pgdba pgdba 0 2008-10-04 12:50 /home/pgdba/data/base/16385/16387
-rw------- 1 pgdba pgdba 0 2008-10-04 12:50 /home/pgdba/data/base/16385/16387_1
Конечно же, теперь FSM хранит полную информацию и не ограничен в размере. Интересно, как много места он занимает. Давайте проверим:
# insert into x (id) select * from generate_series(1,100000);
INSERT 0 100000

# \! ls -l $PGDATA/base/16385/16387*
-rw------- 1 pgdba pgdba 3219456 2008-10-04 12:53 /home/pgdba/data/base/16385/16387
-rw------- 1 pgdba pgdba 24576 2008-10-04 12:53 /home/pgdba/data/base/16385/16387_1
# insert into x (id) select * from generate_series(1,100000);
INSERT 0 100000

# \! ls -l $PGDATA/base/16385/16387*
-rw------- 1 pgdba pgdba 6430720 2008-10-04 12:53 /home/pgdba/data/base/16385/16387
-rw------- 1 pgdba pgdba 24576 2008-10-04 12:53 /home/pgdba/data/base/16385/16387_1
# insert into x (id) select * from generate_series(1,100000);
INSERT 0 100000

# \! ls -l $PGDATA/base/16385/16387*
-rw------- 1 pgdba pgdba 9641984 2008-10-04 12:53 /home/pgdba/data/base/16385/16387
-rw------- 1 pgdba pgdba 24576 2008-10-04 12:53 /home/pgdba/data/base/16385/16387_1
Ок, отсюда видно, что он не увеличивается в размере, когда я добавляю записи в таблицу.

Но, может это из-за того, что таблица очень маленькая, всего 1177 страниц. Проверим на чём-нибудь большем:
# drop table x;
DROP TABLE

# create table x (id int4, dummy_text text);
CREATE TABLE

# alter table x alter column dummy_text set storage plain;
ALTER TABLE

# select relfilenode from pg_class where relname = 'x' and relkind = 'r';
relfilenode
-------------
16408
(1 row)
На заметку: я сделал alter column set storage plain для хранения всех данных из dummy_text в главной таблице, без компресси - эффективное отключение TOAST.
# insert into x select i, repeat('depesz', 500) from generate_series(1,100000) as i;
INSERT 0 100000

# \! ls -l $PGDATA/base/16385/16408*
-rw------- 1 pgdba pgdba 409600000 2008-10-04 13:05 /home/pgdba/data/base/16385/16408
-rw------- 1 pgdba pgdba 122880 2008-10-04 13:05 /home/pgdba/data/base/16385/16408_1
И что случится, если я сделаю update 50% записей?
# update x set dummy_text = repeat('_test_', 500) where id <= 50000;
UPDATE 50000

# \! ls -l $PGDATA/base/16385/16408*
-rw------- 1 pgdba pgdba 614400000 2008-10-04 13:09 /home/pgdba/data/base/16385/16408
-rw------- 1 pgdba pgdba 172032 2008-10-04 13:08 /home/pgdba/data/base/16385/16408_1
Это говорит, что излишек данных на диске составляет около 0.03%, что является незначительным.

Выгоды? У нас теперь одним поводом для беспокойства меньше (слишком маленькие значения параметров FSM) и основание для будущего кода, который сделает vacuum быстрее. Намного быстрее.

No comments:

Post a Comment