- PVSM.RU - https://www.pvsm.ru -
Приятно видеть знакомые фамилии в списке Acknowledgments официального релиза PostgreSQL 12. Мы решили свести вместе попавшие в релиз новшества и некоторые багфиксы, над которыми трудились наши разработчики.
(В Release Notes [1] это звучит как Add support for the SQL/JSON path language (Nikita Glukhov, Teodor Sigaev, Alexander Korotkov, Oleg Bartunov, Liudmila Mantrova)
Сам этот патч, возможности JSONPath и история вопроса обсуждались в деталях в отдельной статье [2] здесь на харбре. JSONPath — серьезное достижение Postgres Professional и одно из главных новшеств PostgreSQL 12 вообще.
В 2014 году А.Коротковым, О.Бартуновым и Ф.Сигаевым было разработано расширение jsquery [3], вошедшее в результате в версию Postgres Pro Standard 9.5 (и в более поздние версии Standard и Enterprise). Оно дает дополнительные, очень широкие возможности для работы с json(b).
Когда появился стандарт SQL:2016, оказалось, что его семантика не так уж сильно отличается от нашей в расширении jsquery. Не исключено, что авторы стандарта даже поглядывали на jsquery, изобретая JSONPath. Нашей команде пришлось реализовывать немного по-другому то, что у нас уже было и, конечно, много нового тоже.
Хотя специальный патч с функциями до сих пор не закоммичен, в патче JSONPath уже есть ключевые функции для работы с JSON(B), например:
jsonb_path_query('{"a": [1,2,3,4,5]}', '$.a[*] ? (@ > 2)') возвращает 3, 4, 5
jsonb_path_query('{"a": [1,2,3,4,5]}', '$.a[*] ? (@ > 5)') возвращает 0 записей
Кроме того, были оптимизированы [4] и некоторые функции, которые уже работали с JSON раньше. Этим успешно занимался Никита Глухов.
Например, оператор #>>, соответствующий функциям jsonb_each_text() и jsonb_array_elements_text(), раньше достаточно быстро преобразовывал JsonbValue в text, но работал неторопливо с другими типами. Сейчас всё работает быстро.
(Add support for nearest-neighbor (KNN) searches of SP-GiST indexes. Nikita Glukhov, Alexander Korotkov, Vlad Sterzhanov)
Никита Глухов и Александр Коротков из нашей компании продолжили работу, начатую Владом Стержановым из Минска (он же Quadrocube). Postgres был первой СУБД, которая реализовала поиск ближайших соседей — раньше Oracle и MS, причём гораздо более прямым и удобным способом — и это заслуга Олега Бартунова и его команды. Идея этого поиска в оригинальном алгоритме обхода дерева, дающем в большинстве случаев огромный выигрыш. Поиск ближайших соседей используется много где, но в ГИС особенно часто.
Влад сделал патч KNN-поиска для для работы с пространственными индексами SP-GiST для quad-деревьев, когда плоскость делят на квадраты фиксированного размера, и для KD-деревьев, то есть k-мерных деревьев.
Александр Коротков, ментор Влада по GSoC (Google Summer of Code), продолжил разработку с коллегой из Postgres Professioanl Никитой Глуховым. Была серьезно обогащена функциональность: улучшено внутренние кэширование данных при обходе дерева, добавлены классы операторов для окружностей и многоугольников с упорядочением по расстоянию.
Чтобы воспользоваться алгоритмом поиска ближайших соседей, достаточно написать ORDER BY [выражение, содержащее оператор расстояния], и тогда оптимизатор автоматически подключит этот алгоритм. Например,
SELECT * FROM polygons
ORDER BY poly <-> point '(0,0)';
Патчи Никиты Глухова можно увидеть на гитхабе [5].
(В Release Notes [6] это Improve speed of btree index insertions by reducing locking overhead. Alexander Korotkov)
Александру Короткову, главному системному архитектору Postgres Professional, удалось придумать более разумный алгоритм блокировок при вставке в индексы B-tree. Выигрыш после применения этого патча заметен в случаях, когда вставка происходит более или менее «подряд». Измерения на 72-ядерном сервере показали, что в этом случае выигрыш доходит до 50%. При хаотичной вставке выигрыш не так заметен.
(Reduce the WAL write overhead of GiST, GIN, and SP-GiST index creation. Anastasia Lubennikova, Andrey V. Lepikhov)
Эта серия патчей позволяет сократить WAL-трафик [7], генерируемый при создании индексов GiST, GIN и SP-GiST. Теперь можно логировать страницы таких индексов только один раз — в конце, когда индекс уже построен. А в случае ошибки при построении индекса записи в WAL о неудачных попытках вообще не появятся. Раньше такое было возможно только при создании B-tree и RUM. Патчи используют механизм generic WAL [8].
Для проверки размера xlog приложены скрипты. Тестирование на базе данных IMDB (формат JSON), в которой 4М+ записей, занимающих 4ГБ, показало:
CREATE INDEX ON imdb USING gin(jb jsonb_path_ops);
старым способом исполнялся 205 секунд, WAL 3.2 ГБ, а новый алгоритм дал 133 секунды, и WAL 0.4 ГБ.
(Allow index-only scans to be more efficient on indexes with many columns. Konstantin Knizhnik)
При анализе работы базы одного из клиентов нашей компании обнаружилось [9], что один и тот же запрос исполняется в некоторых случаях дольше на 25% с index only scan, чем с index scan (enable_indexonlyscan = off).
Это происходило, когда SELECT выполнялся по многим полям, которые имели в основном тип bytea, и их офсеты не кэшировались, так как у таких полей нет фиксированного смещения (об этом см. также доклад Николая Шаплова «Что у него внутри» [10]). Чтобы распаковать k-й атрибут, надо распаковать предыдущие k-1. Распаковка записи по одному атрибуту требует O(N*N) времени, где N — число полей. Эти 25% случились уже при 10 полях.
Константин Книжник воспользовался алгоритмом, который используется при работе с хипом: при обращении к k-ому атрибуту, достаются и запоминаются предыдущие k-1, время растет линейно с числом полей. После применения патча время выполнения с index scan и index only scan практически не отличается.
(Add a wait event for fsync of WAL segments. Konstantin Knizhnik)
Ядро PostgreSQL мониторит запись в WAL, но не следит за сбросом сегментов WAL из памяти на диск, то есть за fsync. К.Книжник сделал патч, который создает новый тип события, оно называется теперь WALSync (внутреннее имя переменной WAIT_EVENT_WAL_SYNC). Его можно увидеть в табличке PG-событий [11] с пояснением «Ожидание сброса WAL-файла в надежное хранилище». Этот вопрос обсуждался [12] в рассылке hackers.
Как долго происходит сброс, обычно неизвестно: стандартный PostgreSQL не умеет агрегировать такую статистику. Но есть расширение pg_wait_sampling [13], написанное в Postgres Professional. Оно умеет рассказывать о том, в ожидании каких событий Postgres проводит время. Теперь, когда событие добавлено, можно следить и за fsync.
(Update Snowball stemmer dictionaries with support for new languages. Arthur Zakirov)
Раз конференции по Postgres проходят в Непале, куда уж естественней добавить [14] непальский язык в базу! Это и было сделано. Благодаря усилиям Артура Закирова теперь можно пользоваться непальским стемминг-словарем на Snowball.
(Adjust to_timestamp()/to_date() functions to be more forgiving of template mismatches, Artur Zakirov, Alexandehttps://postgrespro.ru/docs/postgresql/12/logfile-maintenancer Korotkov, Liudmila Mantrova)
Функция to_timestamp() не работала, если обрабатывалась строка формата с лишними пробелами. Обсуждение бага в to_timestamp() вылилось в пространную дискуссию [15] о том, какое поведение функций to_timestamp() и — заодно — to_date() считать правильным. К всеобщей выгоде обе функции стали более терпимыми к лишним пробелам в строке формата и строке ввода.
(Allow control of log file rotation via pg_ctl. Kyotaro Horiguchi, Alexander Kuzmenkov, Alexander Korotkov)
Другими словами [16] утилита pg_ctl обзавелась новой опцией:
pg_ctl logrotate [-D каталог_данных] [-s]
Когда выполняется эта команда, сервер либо переключается на новый файл журнала, либо заново открывает существующий, в зависимости от конфигурации журналирования [17]. Это может понадобиться при внештатных ситуациях, особенно когда огромные, быстронаполняющиеся лог-файлы нужно, допустим, передать для диагностики.
(Add CREATE ACCESS METHOD command to create new table types. Andres Freund, Haribabu Kommi, Álvaro Herrera, Alexander Korotkov, Dmitry Dolgov)
Этот важный патч — существенная часть инфраструктуры Pluggable Storage API, отсюда и международный состав разработчиков патча. Команда CREATE ACCESS METHOD работает в Postgres с версии 9.6. Но до 12-й можно было только создавать индексные методы доступа. Вот что в документации 11-й версии [18]:
CREATE ACCESS METHOD имя
TYPE тип_метода_доступа
HANDLER функция_обработчик
< ... >
тип_метода_доступа
Это предложение задаёт тип создаваемого метода доступа. В настоящее время поддерживается только INDEX.
А в документации к 12-й уже читаем [19]: в настоящее время поддерживается только TABLE и INDEX. Межу прочим, в 11-й команда CREATE ACCESS METHOD обеспечивалась расширением Postgres Pro, а в 12-й — уже PostgreSQL.
Исполнение операции зависит от типа метода доступа; если это тип TABLE, то обрабатывать будет table_am_handler, а если тип INDEX, то index_am_handler (раньше: для методов доступа типа INDEX это должен быть index_am_handler). Появилась целая глава в документации [20] о табличных методах.
При создании таблицы теперь можно задавать ее тип:
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] имя_таблицы ( [
< ... >
[ USING метод ]
метод имеет тип TABLE — это и есть отсылка к Pluggable Storage. Теперь он heap по умолчанию, а раньше другого, собственно, и не было. О классах операторов здесь [21]
default_table_access_method (string)
Этот параметр задаёт табличный метод доступа по умолчанию, который будет использоваться при создании таблиц или материализованных представлений, если в команде CREATE не будет явно указан метод доступа, или при выполнении команды SELECT… INTO, в которой явно задать метод доступа нельзя. Значение по умолчанию — heap. Большая дискуссия в hackers [22] поможет разобраться в деталях.
До этого момента мы говорили о новшествах. Но ресурсы времени программистов отъедает и исправление багов. Главные из них:
Extra quote_all_identifiers in _dumpOptions. Arthur Zakirov)
В общем, ничего особенного, найдена ошибка в одной из структур, которые использует pg_dump — ее пропустил компилятор. Но сам Брюс Момджян похвалил [23] за находку.
О других проблемах с DumpOptions можно почитать здесь [24].
(xlogreader: do not read a file block twice. Arthur Zakirov)
Другой сотрудник нашей компании, разработчик pg_probackup [25] Григорий Смолкин обнаружил, что одна из наших утилит тормозится, когда xlogreader читает zlib-архивы. Оказалось, что иногда он читает файловые блоки WAL дважды.
Если архивы читаются непоследовательно, то производительность оставляет желать лучшего. Повторное чтение блока всегда непоследовательно, так как приходится возвращаться к пройденной позиции вызовом функции gzseek(). Теперь [26] лишнего перечитывания не происходит.
P.S. Не буду лукавить: дюжина патчей (строго говоря дюжина серий патчей) не просто случайное совпадение с номером версии Postgres. Список вполне мог бы быть недо-дюжиной или сверх-дюжиной. Мне подумалось, что так будет красивей, а красота отчасти и двигатель программирования, не говоря о других областях человеческой деятельности.
Автор: Igor_Le
Источник [27]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/postgresql/334816
Ссылки в тексте:
[1] Release Notes: https://www.postgresql.org/docs/12/release-12.html
[2] в отдельной статье: https://habr.com/ru/company/postgrespro/blog/448612/
[3] jsquery: https://postgrespro.ru/docs/postgrespro/11/jsquery
[4] были оптимизированы: https://www.postgresql.org/message-id/flat/7c417f90-f95f-247e-ba63-d95e39c0ad14%40postgrespro.ru
[5] на гитхабе: https://github.com/glukhovn/postgres/commits/knn_spgist
[6] Release Notes: https://www.postgresql.org/docs/12/release-12.html#id-1.11.6.5.5
[7] сократить WAL-трафик: https://www.postgresql.org/message-id/flat/a055f129-518e-3eac-1242-833d58edfddb@postgrespro.ru
[8] generic WAL: https://postgrespro.ru/docs/postgresql/12/generic-wal
[9] обнаружилось: https://www.postgresql.org/message-id/flat/e06b2d27-04fc-5c0e-bb8c-ecd72aa24959%40postgrespro.ru
[10] «Что у него внутри»: https://pgconf.ru/2016/90059
[11] табличке PG-событий: https://www.postgresql.org/docs/12/monitoring-stats.html#WAIT-EVENT-TABLE
[12] обсуждался: https://www.postgresql.org/message-id/flat/4a243897-0ad8-f471-aa40-242591f2476e%40postgrespro.ru
[13] расширение pg_wait_sampling: https://github.com/postgrespro/pg_wait_sampling
[14] добавить: https://www.postgresql.org/message-id/flat/20180219140849.GA9050%40zakirov.localdomain
[15] пространную дискуссию: https://www.postgresql.org/message-id/flat/1873520224.1784572.1465833145330.JavaMail.yahoo%40mail.yahoo.com
[16] Другими словами: https://postgrespro.ru/docs/postgresql/12/logfile-maintenance
[17] конфигурации журналирования: https://postgrespro.ru/docs/postgresql/12/runtime-config-logging#RUNTIME-CONFIG-LOGGING-WHERE
[18] в документации 11-й версии: https://postgrespro.ru/docs/postgresql/11/sql-create-access-method
[19] уже читаем: https://postgrespro.ru/docs/postgresql/12/sql-create-access-method
[20] глава в документации: https://postgrespro.ru/docs/postgresql/12/tableam
[21] здесь: https://postgrespro.ru/docs/postgresql/12/sql-createopclass
[22] в hackers: https://www.postgresql.org/message-id/flat/20160812231527.GA690404@alvherre.pgsql
[23] похвалил: https://www.postgresql.org/message-id/flat/d3d92ce9-78a4-8adb-0393-d3deeec29f7e%40postgrespro.ru
[24] здесь: https://www.postgresql.org/message-id/flat/CACw0%2B13ZUcXbj9GKJNGZTkym1SXhwRu28nxHoJMoX5Qwmbg_%2Bw%40mail.gmail.com
[25] pg_probackup: https://github.com/postgrespro/pg_probackup
[26] Теперь: https://www.postgresql.org/message-id/flat/2ddf4a32-517e-d6f4-d992-4a63b6035bfd%40postgrespro.ru
[27] Источник: https://habr.com/ru/post/472072/?utm_source=habrahabr&utm_medium=rss&utm_campaign=472072
Нажмите здесь для печати.