Pull to refresh
96
0.1

PostgreSQL DBA

Send message

ничего не произойдёт ни с FK, ни с триггерами, ни с ссылающимися на таблицу чем бы то ни было ещё. Фактически объявление таблицы мы вообще не трогаем, только подменяем relfilenode новым. Это довольно просто и надёжно (в том числе для новых фич), но зато делает невозможным реализацию каких-нибудь на первый взгляд уместных дополнительных возможностей: изменение типа данных колонки, например, или переупорядочивание колонок в таблице.

партицирование умеем. Я рекомендую запускать непосредственно на каждую индивидуальную партицию чем через голову.

visibility map сбросится как побочный эффект, да. Если активно используется index only scan для запроса - ему поплохеет.

pg_repack maintainer и автор патчей для поддержки всех версий postgresql начиная с 11.

Следит за всеми изменениями в оригинальной таблице (использует триггеры и лог WAL).

WAL мы не используем для отслеживания изменений

Создает временную «чистую» таблицу‑копию и индексы.
Копирует в нее все актуальные данные.

корректности ради: сначала создаём таблицу, потом пишем в неё копию данных из таблицы-источника, только потом создаём новые индексы

Блокировка все еще нужна, но только на пятом шаге и длится миллисекунды.

блокировку мы вынуждены брать дважды: в самом начале, т.к. create trigger требует аналогично блокировку, и в конце для подмены relfilenode на новые.
Миллисекунды блокировки только если никто не мешает (к таблице только быстрые запросы и их можно раздвинуть безболезненно), а вот если к табличке ещё постоянным фоном транзакции по несколько минут - остановите эту активность на время репака либо не ставьте опцию no-kill-backend чтобы репак прибил те транзакции которые мешают взять блокировку.

SELECT repack.repack_table('bloated');

это некорректный способ запуска pg_repack. Если это локальный патч вашего форка - упомяните это, пожалуйста, явно.

по vacuum (не full) - почему в табличке отмечено "Даунтайм для приложения" "да"?

ну и есть у вакуума одна особенность: он действительно может уменьшить таблицу. Но только хвост датафайлов. То есть от конца таблицы до самого дальнего тапла который не был удалён и вычищен. И зная это, если ещё вариант сжатия таблиц: https://github.com/dataegret/pgcompacttable/blob/master/bin/pgcompacttable
переместить оставшиеся живые таплы из конца таблицы, затем обычный vacuum действительно вернёт место ОС. Это особо полезно, когда нет троекратного запаса по месту на дисках (на новую копию данных, индексы, и всё это записать в WAL)

Устройство поддерживает декодирование видео в формате 4K со скоростью 60 кадров в секунду.

а дальше куда? Нет же какого-либо видеовыхода?

Специально придуманные ИБП, ага, как бы не так... В реальной жизни:
один ИБП просто вырубает нагрузку "а что, у вас какая-о мелочь там, а мы green!!"
другой не включает нагрузку после возвращения электроснабжения пока не ткнёшь кнопку
третий именно что не успевает переключиться на батарею, роутер ребутается
и попробуй это всё выяснить не экспериментально

О, ключевое слово Pass-Through Charging для поиска это полезно. У меня роутер от type C питается, иногда думаю не заменить ли UPS на повербанк, но непонятно какие смогут работать.

Опять чатгпт писал?
Комментарии к pg_stat_statements.track и track_activity_query_size просто неверны, а требуемый для активации pg_stat_statements shared_preload_libraries вовсе не упомянут.
total_time в pg_stat_statements давно уже нет, во время добавления total_plan_time (если включен pg_stat_statements.track_planning) был переименован в total_exec_time.

wal_level = archive давным-давно deprecated псевдоним для wal_level = replica

Слот репликации - это механизм, который используется для передачи WAL записей от мастера к реплике без необходимости активного участия реплики.

неверно. Слот физической репликации - это механизм, гарантирующий что у вас переполнится диск на мастере, но не будут удалены WAL, о получении которых ещё не отчиталась реплика.
Соответственно, вы вообще никак не пояснили, зачем вам вообще слот репликации. (хинт: он просто не нужен для pitr)

Где вы нашли синтаксис ALTER SLOT для меня, конечно, загадка. Нет такой синтаксической конструкции даже в pg17.

Ну и последнее, но самое важное: вся статья исключительно по EOL версиям postgresql и не подходит для более новых. pg_xlog* функций не существует с pg10, а чтение файла с именем recovery.conf удалил лично я начиная с postgresql 12. Это конечно объясняет пример с archive wal_level, зато вызывает вопросы к "онлайн-курсу"

Да, wal_compression вполне заметно работает, даже при том что только на full page image записях применяется. Сжатие производится до записи WAL как такового, а потому снижает не только объёмы передачи потоковой репликации, но и IO тоже. И к архиву тоже соответственно применяется.

А вот если помимо wal_compression сжимать весь сегмент чем-то ещё сверху - то эффект куда сильнее. Вроде такого

melkij@melkij:/tmp/z$ du -hs *
17M	000000010000003500000034
3,3M	000000010000003500000034.gz
2,2M	000000010000003500000034.zst

Лидер временно может хранить WAL-ов больше, чем указано в параметре wal_keep_size (например, из-за долгой транзакции)

Мастер может в любой конфигурации хранить WAL'ов больше чем указано где-либо потому что ограничения на максимальный объём WAL просто нет.
И нет, wal_keep_size не имеет никакого отношения к долгим транзакциям. У нас REDO, не волнует возраст транзакций ни для crash recovery ни для удержания WAL, нас волнует LSN который записали при чекпойнте и соответственно откуда стартовать recovery. А уже при crash recovery смотрим, встретили ли commit запись в WAL или нет.

Вот то, что wal_keep_size держит постоянно занятый объём, я, впрочем, и вовсе как недостаток не рассматриваю - это вполне неплохой удобный резерв наравне с reserved space в ext4. Надо освободить место - оговариваем, что тогда могут отвалиться дальние/медленные реплики. Зато когда медленные реплики действительно отстают - у нас не начинает исчезать свободное место.

Я понимаю, что если тащить WAL-ы из той же Москвы в Новосибирск, то идея с архивной репликацией быстро умрет :)

Я бы кстати наоборот ожидал что на фиговой сети file shipping репликация будет менее проблемная. WAL'ы в виде файликов неплохо сжимаются и сжатие wal просто добавить для архива (по-моему, это вообще дефолтный режим в wal-g). А вот streaming репликация гоняет несжатые данные. При том, потоковая репликация ходит строго одним TCP коннектом. Если нет своих сетевых инженеров для тюнинга сетевого стека, то кучка маленьких параллельных TCP сессий на нестабильной сети наверняка будут работать лучше чем одно долгоживущее.

Ну и в плюсы репликации через архив можно добавить, что для этого способа не надо прорубать сетевое окно на подключение до рабочих баз через всевозможные VPN и файрволы по пути. Базу можно изолировать в закрытом сетевом контуре, куда извне не подключиться.
Плюс гибкость выбора транспортировки WAL, хоть по RFC 1149 кидать.

Как обычно, какую задачу решаем?

Если вам нужна гарантия, что все WAL сохранены где-то ещё - то начать нужно с вопроса, что вы хотите что бы делала база когда это невозможно. Ну вот буквально, транзакция хочет сделать insert данных. Что делать базе? Разрешить выполнить запись сразу и закоммитить? Всё, тут мы уже нарушили гарантию доставки WAL. У нас есть кусочек WAL, который существует только локально на этой базе и ещё не был никуда скопирован. Для этой задачи нужна синхронная репликация. При том, иметь в виду, что insert в postgresql выполнен будет в любом случае при активной синхронной репликации, синхронная репликация гарантирует что ответ базы "commit выполнен" будет получен после доставки WAL на указанную конфигурацию синхронных реплик. При проблемах с синхронной репликацией останавливается запись данных, но раз просили гарантию сохранности - то вот она цена.

Хотим чтобы реплика могла догнать после существенного отставания репликации?
гарантированно? слот репликации без ограничения, либо архив WAL если он очищается с учётом отставания этой реплики. Хочу обратить внимание, что если archive_command перестаёт работать - то база будет накапливать WAL безгранично, подобно слотам репликации max_slot_wal_keep_size. Зато скорей всего под архив WAL получится выделить куда более вместительное и более дешёвое хранилище. Цена той гарантии, что реплика догонит - потенциально неограниченный расход места на хранение WAL.
после разумного объёма отставания? wal_keep_size либо слот репликации с max_slot_wal_keep_size, либо архив WAL если тот очищается независимо от отставания реплики

Но вообще архив WAL обычно заводят когда нужен point-in-time-recovery, а не для репликации. И это другая задача. А потом уже, раз всё равно пишем архив WAL, - то можно и задействовать restore_command чтобы из него подтягивать недостающие WAL для отстающих реплик, попутно.

В большинстве production систем действительно лучше потерять реплику и переналить заново, чем уронить мастер с переполнением диска. Поэтому мы почти всегда используем только wal_keep_size. Если реплика отстала до requested WAL segment ... has already been removed и ничего не могли сделать после того как мониторинг сказал что реплика отстаёт - то переналить заново. Зато не потеряли мастер.

restore_command, кстати, имеет одно не очень явно задокументированное свойство: он имеет безусловный приоритет над WAL уже сохранёнными в pg_wal. То есть даже если у вас все WAL есть локально у базы во время старта, то всё равно они будут заново читаться из архива. Поэтому если у вас архив wal не очень быстрый на чтение - то restore_command будет замедлять все рестарты баз.

гхм, а что за фс в 2023 не поддерживают trim?

а можно не "не поддерживает", а "не использует по умолчанию"? Тогда - большинство. Для большинства файловый систем опция discard в linux выключена по-умолчанию. См. https://wiki.archlinux.org/title/Solid_state_drive со ссылками на rhel/ubuntu/debian и вовсе ядро linux с целым списком девайсов с серьёзными ошибками в прошивках, из-за которых для них персонально отключают часть функциональности.

Вместо discard дистрибьютивы обычно делают в кроне или по systemd таймеру вызов fstrim раз в неделю или около того.

Хочу напомнить, что в отличии от распространённых практик другого софта, для mysql х.0 релиз даже изначально не планируется как General Availability релиз, и это даже не бета. Это просто Development Milestone "мы хотим чего-нибудь показать". До General Availability ещё пара лет.
Не вижу, чтобы для 8.1 эта политика менялась.

Для нормального использования, конечно, лучше всего TLC

ну вот лет через несколько точно так же и про QLC говорить будут, как про TLC лет 5 назад было "кому нужен одноразовый SSD"
Уже и PLC flash из лабораторий выходит, как раз.

так вам просто некуда писать после быстрого заполнения четверти диска для QLC либо трети диска при TLC. Всё, ёмкость кончилась, если до сих пор писали 1 бит в ячейку. Несколько процентов избыточности флеша вам дадут, но ставить 2тб флеша и продавать как 1тб не будут точно.
А дальше попадаем на серьёзный штраф времени на erase блока, который исключает всякий смысл неполной записи ячейки. По-моему, возможность ускориться есть только для такого псевдо SLC однобитового режима, или же уже нет смысла (а то и возможности) извращаться и нужно писать номинальное количество бит на ячейку.

Как будет падать график - больше от прошивки контроллера зависит, чем от чего-то другого.

Неа, одинаковые там чипы. Нюанса два:

  • при записи данных во flash это не просто взяли и записали байтики (write), а писать можно только в подготовленные, очищенные ячейки (erase). И вот erase - это весьма долго по сравнению с собственно записью, а ещё может выполняться только блоками относительно физической структуры NAND.

  • как пишется TLC (да и QLC тоже). Это не взяли битики и записали за один раз все 3 (4 у qlc) битики в ячейку. Процесс многостадийный. Следовательно - более медленный. При этом, есть физическая возможность прерваться после записи одного бита в ячейку, затратив при этом соответственно меньше времени (сильно меньше времени).

Ну и вот она, возможность в бенчмарках показать какие-нибудь красивые цифры. Сообщить (discard) накопителю, что данных на нём нет, дать ему время поработать над erase своих ячеек своего флеша. Дать нагрузку на запись, контроллер делает фокус с записью только одного бита в ячейку. Пока есть свободные ячейки (и не дошли до софтовых ограничений в прошивке, например, использовать только такую-то ёмкость в таком стиле) - получаем качественное ускорение записи. Маркетинг в восторге.
А вот как свободные ячейки кончаются, но запись так и не прерывали - скорость записи резко падает. Контроллеру теперь нужно освобождать место на флеше. Читать записанное ранее, переписывать в полноценном TLC режиме, делать erase освобождённых ячеек, писать, в конце концов, то что продолжает требовать записать ОС.

Зато если запись случается нечастыми такими скачками, ОС сообщает об удалении данных (TRIM), а пользователь не забивает диск к 100% - то всё равно остаётся вполне хорошее ускорение для большинства пользователей. Это делают практически все десктопные модели, ориентация на нечастые спринтерские забеги, но не под постоянную запись. Ну а то что маркетинг об этом, разумеется, не скажет - как будто что-то неожиданное.

Да и многие серверные делают так же, вполне себе состоялось деление на разные семейства SSD под Read Intensive (см. выше) или же write-intensive (запись будет плюс-минус стабильна под постоянной пишущей нагрузкой, но дорого).

ну, на самом деле действительно нетипично на сервере ставить систему, которой осталось пара недель до EOL. Вообще не LTS убунта на сервере настораживает.

performance testing is the state of art (c)

железо:
поизучать наработки годов этак 2006-2012 overclokers, fcenter, ixbt и других грандов былых времён по части тестовых стендов и методик сравнения различающегося железа. Особенно методики тестирования i7 920 как первого 3-канальника. Какие шишки на нём собрали, как сглаживали эффекты различия объёма, как тестировали изменение числа каналов памяти.

одну и ту же пару дисков переставлять физически в каждый сервер. В начале короткий fio минут на 5 для детектирования аномалий, различия результатов теста между серверами, понятное дело, должно быть минимально. Если это не так - то искать причину.
желательно использовать одну и ту же коллекцию модулей памяти, с проверкой что они стартуют в одинаковом режиме частота&тайминги среди всех участников
влияние разной конфигурации заполнения слотов памяти - идея для тестирования платформы в отдельности, на самом деле. Это лично мне, кстати, действительно интересно - имеет ли значение число каналов памяти кроме как для увеличения максимального объёма памяти. Максимум памяти в реальности не столь актуален для СУБД, даже террабайт RAM очень мало кто ставит, а вот есть ли смысл просить именно задействовать каналы памяти, а не добить до нужного объёма теми модулями что под рукой нашлись?
на разных платформах соответственно дать настолько близкую разбивку модулей по каналам и сокетам насколько получится, различия задокументировать
контроль температуры и троттлинга на протяжении тестов (для серверов тоже не шутка, да, была у нас машинка в ovh (вполне серверный xeon D-2141I, не десктоп), которая под нагрузкой перегревалась и сбрасывала частоту CPU втрое)

ОС:
NUMA. NUMA это проблема. Честно не знаю как сглаживать его артефакты кроме как переключением всей системы в interleave либо сознательно через numactl тестировать только половину сервера. Особое счастье с EPYC'ами, где по 4 NUMA ноды бывает даже в одном сокете.
cpu performance mode. В реальности под базой данных CPU решает выходить из powersafe и поднимать частоту до рабочей довольно поздно (мой опыт - это разница в полтора раза по графикам среднего времени выполнения запросов от веба). Но главное для теста - непостоянно. performance mode нам тоже не даст постоянную рабочую частоту, но куда лучше чем powersafe.

postgres
ох (с)
сейчас я упомянут даже в списках разработчиков postgresql, но понимания как корректно тестировать его производительность стало даже меньше, чем когда я про него даже не знал =)
pgbech - ну, это pgbench. Чистая синтетика, довольно бесполезная сама по себе. А вот что-то полезное моделировать... (за это DBA не любят детей ораклового маркетинга "у нас 10k tps, справится postgres?" - каких именно транзакций-то?)
Разглядел, кстати, затаивщийся в опциях scale factor, с первого раза не признал его в краткой форме. То есть примерно 150гб рабочий набор у вас на начало теста. Боюсь, что на самом деле протестировали менеджер локов и реализацию spinlock нежели собственно производительность запросов: все операции над данными postgres выполняет только в shared_buffers, а он в дефолте аж целых 128МБ. Получается конкурентные процессы активно дрались между собой, чтобы скопировать из page cache системного в shared buffers нужный именно этому процессу блок (памяти явно достаточно во всех случаях, чтобы реально на диск только писать, но не читать). А вот со spinlock'ами на ARM у postgresql действительно не всё хорошо: https://www.postgresql.org/message-id/flat/CAB10pyamDkTFWU_BVGeEVmkc8%3DEhgCjr6QBk02SCdJtKpHkdFw%40mail.gmail.com Скорей всего так до сих пор не оптимальный машинный код и компилируется в GCC для ARM.
Поскольку тестировать хотим CPU, в меньшей мере память и не хотим диск, то стоит поставить shared_buffers гигабайт в 180 (хотя на сотне процессов уже может отвалиться вот тот конфиг на 192гб памяти с OOM), synchronous_commit = off. huge_pages = on на таком объёме памяти уже точно нужен (соответственно в ОС тоже выделить huge pages)

PS: я понимаю почему выбрана модель "специально ничего не настраиваем", в этом есть смысл, но по моему опыту shared_buffers всё-таки пользователи крутят чуть менее чем всегда, думаю полезнее чем дефолтные 128мб тестировать будет.

Не всегда, да. Но вы это не указали в статье. Поискал внимательнее, в описании конфигурации вы вообще никак не упоминаете ни модели дисков, ни что они хотя бы одноклассники. Честно не помню, какие диски вы ставите обычно, для нас вы собирали кастомные конфигурации с оговорёнными конкретными моделями дисков под write intensive базы. Но часто если хостер говорит в описании что поставит абстрактное "2 × 960 ГБ SSD NVMe", то на двух одинаковых заказанных одновременно серверах запросто можно увидеть разные диски (а то и на одном сервере две разные модели, привет hetzner'у).

Различие конфигурации должно устраняться или хотя бы подтверждаться тестом, что оно не является значимым фактором для результата тестирования. У вас есть тест, что различие в объёме RAM 192 и 512гб не имеет значения для результата теста? (а про частоту и тайминги вы тоже не писали в статье)
В частности, вы так же не указали, сколько у вас каналов памяти вообще работает. Для того же восьмиканального 6336Y может быть значимым различие, установлено ли 16 модулей по 16гб или 8 по 32гб или максимальным поддерживаемым объёмом одного DIMM (4 по 64? 2 по 128?).

Объём разный. Особенно на не топовых по объёму моделях это очень часто означает разницу производительности. Иногда кратную.
Ну например, самсунговый PM9A3 https://semiconductor.samsung.com/ssd/datacenter-ssd/pm9a3/ :
объёмом 960гб - 70к IOPS random write, а 1920гб - уже 130к IOPS. Почти двукратно по спецификации. Что там в реальности - тема отдельного вдумчивого теста.

ну я понимаю маркетинг, но заявлять что сравниваете производительность ARM и x86 в базах данных, но ставить разные диски участникам? Это же в принципе лишено смысла. В сравнении должен быть минимум различий. Одна и та же физически пара накопителей должна переставляться с сервера на сервер для корректного сравнения возможностей именно CPU, а не дисков.

Аналогично по RAM, впрочем я не вижу у вас scale factor, так что от него значение меньше.

Корректный заголовок "погоняем синтетику на наших тарифах", исключив при этом из теста кастомную конфигурацию.

1
23 ...

Information

Rating
5,089-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity

Specialization

Database Administrator
Lead
PostgreSQL