- PVSM.RU - https://www.pvsm.ru -

Примеры реальных патчей в PostgreSQL: часть 3 из N

Примеры реальных патчей в PostgreSQL: часть 3 из N - 1

Сегодня я хотел бы вновь рассказать о некоторых патчах, принятых за последнее время в PostgreSQL (а также утилиту pg_filedump). Аналогичные статьи, опубликованные на Хабре ранее, набрали достаточно много плюсиков, что заставляет думать, что они представляют для кого-то интерес. Если вы пропустили предыдущие статьи, вот они — раз [1], два [2], три [3]. Несмотря на то, что рассмотренные патчи были написаны мной, не стоит забывать о вкладе людей, которые их ревьювили и тестировали. Проделанная этими людьми работа зачастую оказывается больше и сложнее работы самого автора. Особо активное участие в разработке рассмотренных пачтей приняли Федор Сигаев, Robert Haas, Tom Lane, Дмитрий Иванов, Григорий Смолкин, Andres Freund, Анастасия Лубенникова и Tels.

11. pg_filedump: возвращение ненулевого кода возврата в случае ошибок

Напомню, что утилита pg_filedump [4] предназначена для декодирования сегментов таблиц и вывода информации о заголовках страниц и кортежей. Было замечено, что при несовпадении контрольных сумм страниц с их содержимым, pg_filedump выводит соответствующее предупреждение, однако возвращает нулевой код возврата. Что как бы не совсем правильно, особенно если утилита используется в shell-скриптах.

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

+/* Program exit code */
+static int exitCode = 0;
+
 /***
  * Function Prototypes
  */
@@ -191,6 +194,7 @@ ConsumeOptions(int numOptions, char **options)
                        {
                                rc = OPT_RC_INVALID;
                                printf("Error: Missing range start identifier.n");
+                               exitCode = 1;
                                break;
                        }

@@ -205,6 +209,7 @@ ConsumeOptions(int numOptions, char **options)
                                rc = OPT_RC_INVALID;
                                printf("Error: Invalid range start identifier <%s>.n",
                                           optionString);
+                               exitCode = 1;
                                break;
                        }

(...и так далее...)

@@ -1746,5 +1823,5 @@ main(int argv, char **argc)
        if (buffer)
                free(buffer);

-       exit(0);
+       exit(exitCode);
 }

Патч: 1c9dd6b728810ea7d2f196e6e15064017e4b9eef [5]

12. Улучшение документации о внутреннем представлении типа timestamp

Документация к типу timestamp гласила:

    When <type>timestamp</> values are stored as eight-byte integers
    (currently the default), microsecond precision is available over 
    the full range of values. When <type>timestamp</> values are
    stored as double precision floating-point numbers instead (a
    deprecated compile-time option), the effective limit of precision
    might be less than 6. <type>timestamp</type> values are stored as
    seconds before or after midnight 2000-01-01. [...]

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

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

Патч: 44f7afba79348883da110642d230a13003b75f62 [6]

13. pg_filedump: частичное восстановление данных

Этот патч был подробно рассмотрен в заметке Пример восстановления таблиц PostgreSQL с помощью новой мега фичи pg_filedump [7], поэтому здесь я не буду на нем подробно останавливаться. TL;DR версия — теперь при помощи pg_filedump можно восстановить по крайней мере какую-то часть данных из таблицы, даже в случае, если инстанс PostgreSQL не запускается.

Патч: 52fa0201f97808d518c64bcb9696f2a350678aa5 [8]

14. pg_filedump: декодирование каталожных таблиц

Как и предыдущему патчу, этому была посвящена целая отельная статья Еще одна новая фича pg_filedump: восстанавливаем каталог PostgreSQL [9]. TL;DR версия для тех, кто все равно не собирается ее читать — раньше pg_filedump не поддерживал некоторые типы, используемые в каталожных таблицах. После применения этого патча стало возможным декодировать таблицы каталога, а следовательно и восстановить схему базы данных, если она нам не известна.

Патч: 5c5ba458fa154183d11d43218adf1504873728fd [10]

15а. Ускорение партицирования: исправление батлнека в find_tabstat_entry() / get_tabstat_entry()

В PostgreSQL 10, который на момент написания этих строк разрабатывается и находится в состоянии фичфриза, была добавлена возможность декларативного партицирования таблиц [11]. То есть, теперь таблицу можно разбить на несколько физических таблиц по хэшу или ренджам. Это было возможно и ранее при помощи наследования таблиц, но было менее удобно и в целом выглядело как грязный хак. Примеры использования декларативного партицирования можно найти здесь [12] и здесь [13].

Ну вот я и подумал, а создам-ка я побольше (скажем, 10 000) партиций и посмотрю, где будет тормозить. Теме профилирования кода на C/C++ ранее я посвящал целую статью [14], даже несколько, если считать статьи про DTrace [15], SystemTap [16] и HeapTrack [17]. Кроме того, на эту тему я делал доклад на HighLoad++ 2016 [18], видеозапись которого лежит на YouTube [19]. Поэтому на описании процесса здесь я подробно останавливаться не буду. Скажу только, что perf top показал два явных батлнека, которые вы можете видеть на иллюстрации в начале данной статьи.

Так вот, патч исправляет первый из этих батлнеков. Оказалось, что статистика по таблицам использует небольшой аллокатор памяти, построенный на списках. Поиск по идентификатору таблицы структуры PgStat_TableStatus, соответствующей таблице, производился путем сканирования этого списка, что работает не очень хорошо, когда таблиц 10 000. Добавление хэш-таблицы, отображающей идентификатор таблицы в указатель на структуру, моментально устранило батлнек.

Патч: 090010f2ec9b1f9ac1124dc628b89586f911b641 [20]

15б. Ускорение партицирования: исправление батлнека в find_all_inheritors()

Аналогичная проблема присутствовала и в процедуре рекурсивного поиска всех наследников заданной таблицы. Немногие знают, что PostgreSQL поддерживает множественное наследование таблиц [21]. Поэтому при обходе дочерних таблиц процедура проходит по списку ранее посещенных таблиц. Если очередной таблицы в списке нет, она в него добавляется. Если она там уже есть, у таблицы увеличивается счетчик родителей. Список всех дочерних таблиц и число их родителей возвращается из процедуры в качестве результата.

Как вы уже могли догадаться, батлнек снова был устранен добавлением хэш-таблицы для ускорения поиска по списку. По моим бенчмаркам два патча суммарно ускорили декларативное партицирование на 64%. Интересно, что патчи ускоряют его не только при большом количестве партиций, но и когда партиций всего лишь несколько штук. Хотя в последнем случае, конечно же, эффект не так заметен.

Патч: 827d6f977940952ebef4bd21fb0f97be4e20c0c4 [22]

Заключение

Как и ранее, цель всех этих статей — показать, что в разработке РСУБД, в частности PostgreSQL, несмотря на крайнюю интересность процесса, нет чего-то волшебного или прямо-таки непостижимо сложного. Хочется надеяться, что эта серия статей сможет мотивировать пару-тройку человек принять участие в разработке PostgreSQL, в качестве хобби, или же профессионально.

В частности, компания Postgres Professional, в которой я сейчас работаю, перманентно нанимает [23], притом, не только программистов, но и, к примеру, QA и DBA. Как уже было отмечено, качественные тестирование и code review в нашем деле зачастую оказываются важнее написания кода.

Автор: Postgres Professional

Источник [24]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/postgresql/251971

Ссылки в тексте:

[1] раз: https://habrahabr.ru/company/postgrespro/blog/308442/

[2] два: https://habrahabr.ru/company/postgrespro/blog/309488/

[3] три: https://habrahabr.ru/company/postgrespro/blog/310372/

[4] утилита pg_filedump: https://wiki.postgresql.org/wiki/Pg_filedump

[5] 1c9dd6b728810ea7d2f196e6e15064017e4b9eef: https://git.postgresql.org/gitweb/?p=pg_filedump.git;a=commitdiff;h=1c9dd6b728810ea7d2f196e6e15064017e4b9eef

[6] 44f7afba79348883da110642d230a13003b75f62: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=44f7afba79348883da110642d230a13003b75f62

[7] Пример восстановления таблиц PostgreSQL с помощью новой мега фичи pg_filedump: https://habrahabr.ru/company/postgrespro/blog/319770/

[8] 52fa0201f97808d518c64bcb9696f2a350678aa5: https://git.postgresql.org/gitweb/?p=pg_filedump.git;a=commitdiff;h=52fa0201f97808d518c64bcb9696f2a350678aa5

[9] Еще одна новая фича pg_filedump: восстанавливаем каталог PostgreSQL: https://habrahabr.ru/company/postgrespro/blog/323644/

[10] 5c5ba458fa154183d11d43218adf1504873728fd: https://git.postgresql.org/gitweb/?p=pg_filedump.git;a=commitdiff;h=5c5ba458fa154183d11d43218adf1504873728fd

[11] декларативного партицирования таблиц: https://commitfest.postgresql.org/12/611/

[12] здесь: https://www.depesz.com/2017/02/06/waiting-for-postgresql-10-implement-table-partitioning/

[13] здесь: https://www.keithf4.com/postgresql-10-built-in-partitioning/

[14] посвящал целую статью: http://eax.me/c-cpp-profiling/

[15] DTrace: http://eax.me/dtrace/

[16] SystemTap: http://eax.me/systemtap/

[17] HeapTrack: http://eax.me/heaptrack/

[18] доклад на HighLoad++ 2016: http://www.highload.ru/2016/abstracts/2356.html

[19] лежит на YouTube: https://www.youtube.com/watch?v=0NU07havVD0

[20] 090010f2ec9b1f9ac1124dc628b89586f911b641: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=090010f2ec9b1f9ac1124dc628b89586f911b641

[21] PostgreSQL поддерживает множественное наследование таблиц: https://www.postgresql.org/docs/current/static/ddl-inherit.html

[22] 827d6f977940952ebef4bd21fb0f97be4e20c0c4: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=827d6f977940952ebef4bd21fb0f97be4e20c0c4

[23] перманентно нанимает: https://postgrespro.ru/jobs

[24] Источник: https://habrahabr.ru/post/325850/