Pull to refresh

Comments 43

UFO just landed and posted this here
И не просто наступал, но и героически преодолевал последствия. До сих пор вздрагиваю.
Можно, конечно, тешить себя мыслью, что Хабрахабр — это такой своеобразный Олимп, где сидят только наикрутейшие профессионалы, но это не так — хабр читают и обычные джуны, которым всё вышеописанное в новинку. Так зачем же кричать «очевидно»? Кому-то, может, и не очевидно совсем.

Могут быть и не только junior-разработчики, но и люди из других областей, которые хотят что-то новое освоить. И вот такие подборки — это очень ценный ресурс для них. То есть, для нас.

Согласованности можно достичь и для денормализованных данных — при помощи составных первичных и внешних ключей. Разумеется, если денормализованные данные — это просто данные с дублированием, а не данные без схемы.


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

Подскажите, откуда взялось, что «Дело в том, что PostgreSQL для каждой временной таблицы создает временный файл…»? Нигде в документации об этом не написано.
Повлияет ли на производительность, если временную таблицу создавать в tablespace на RAM-диске?
Для каждой таблицы создается обычный физический файл. Не временный.
См. реализацию heap_create_with_catalog и конкретно здесь
Извините, я ошибся. Копнул чуть глубже в документацию:
Each table and index is stored in a separate file. For ordinary relations, these files are named after the table or index's filenode number, which can be found in pg_class.relfilenode. But for temporary relations, the file name is of the form tBBB_FFF, where BBB is the backend ID of the backend which created the file, and FFF is the filenode number.


И внимание. При старте (если это действительно только при старте, то похоже на баг) postmaster через
RemovePgTempFiles() в конечном итоге вызывает unlink() для всего, что выглядит как файл временной таблицы.
Судя по форумам tablespace на RAM-диске дает очень высокую вероятность убить всю базу.
"...losing any tablespace would prevent the database server from starting,
even if it was only for temporary things" https://www.postgresql.org/message-id/51806248.60401%40darrenduncan.net

Сообщение датировано 2013 годом. Интересно, как сейчас дела обстоят?
В общем-то большинство пунктов относятся к любой SQL (и не SQL) БД.
На все доводы сторонников денормализации отвечайте, что нормализацию придумали не просто так и молчите с многозначительным видом

Если не используете транзакции, зачем вам тогда РСУБД?
> Не используйте схему public
> Это служебная схема для функций из расширений. Для своих нужд создавайте отдельные схемы. Относитесь к ним как к модулям и создавайте новую схему для каждого логически обособленного набора сущностей.

Почему?
С приложения не получилось оформить как цитрату :(
С помощью схем в PG можно логически группировать таблицы. Писать запросы не мешает, так как всегда можно указать все схемы в schema_search_path сессии и не указывать при именовании таблиц.

Как бонус можно создать таблицы с одинаковым именем в разных схемах для горячих и исторических данных. Тогда можно не меняя запросы подключатся между ними просто указав параметры в сессии.
Статья про безопасность. Так и не понял, чем это чревато, использовать public. Не каких лишает возможностей, а чем чревато.
Это, скорее, правило хорошего тона. Но теоретически, можно получить проблемы конфликта имен при установке расширений, которые используют схему public для своих функций. Маловероятно, но возможно.
А еще перед тем, как запустить код, выдохните, просчитайте до трех и удостоверьтесь, что вы в сессии нужной базы.

Ох, вспоминается случай из жизни. Правда не про СУБД, но в тему торопливости. 2 недели без выходных работал в командировке над проектом. Последний день. Около 6 часов вечера. С утра должен быть самолет домой. Сделал все, кроме небольшого сервиса, который никак не хотел работать. Я решил, что самая хорошая идея — переустановка софта. Заметил, что нахожусь не в той ssh сессии только когда полностью удалил все с одной из важнейших боевых машин. Первая мысль — накрылся мой перелет и грядет нарушение визового режима. Но в итоге это была моя самая быстрая установка и настройка за всю жизнь: уже к 9 вечера все было настроено вместе с тем небольшим сервисом.
Кстати, а что там нынче хорошего читают про PostgreSQL? Eng/рус, все равно, главное — специфика и тонкости работы. Что док есть, я знаю.

возможно, здесь вы найдете что-нибудь интересное (blogs, articles, tutorials)

Круто, благодарю!
Я еперд DELETE или UPDATE всегда пишу BEGIN.
darthunix п.22… именно поэтому к базе данных создают несколько подключений под одним пользователем, в которые заворачивают сотни пользователей с сервера. Не делайте так, одним словом, иначе придется при росте нагрузки все переписывать.

Не совсем понятно, что не нужно делать? Создавать на каждого пользователя приложения — пользователя в БД? Или наоборот?
А так, советы подходят почти к каждой СУБД, но спасибо за наводку на специфичные для Postgesql инструменты.
Я и правда не очень четко выразился. Речь о том, что создавать для каждого пользователя приложения своего пользователя в БД — очень плохая практика. При дальнейшем росте нагрузок (а они растут внезапно и незапланированно) это обернется невозможностью использовать пулы соединений к базе.
Пожалуйста, перепишите пункт 22,
иначе ваша мысль совсем не доходит
(я уж подумал, что только до меня не доходит).
Поправил, это и правда было написано плохим стилем.
п7 совсем неясен. зачем несогласованность в транзакции? кому от этого лучше?
deferrable initially deferred только затруднит поиск ошибки.
Вы получите согласованность на конец выполнения транзакции и (опционально) на любой момент внутри ее. Это позволяет упростить жизнь при вставке данных одной транзакцией в разные таблицы, где из-за внешних ключей нужно иначе было бы учитывать порядок вставки. Плюс это иногда удобно при импорте данных через insert.
это совсем не похоже ни на технику безопасности ни на «хорошую практику»
применимо к приложению это создает исключения только на этапе коммита, вместо генерации исключения на этапе insert/update/delete, что точно плохо сказывается на диагностике неполадки.
К тому же, поддерживать согласованность всегда полезно для выстраивания логики кода. Гораздо сложнее выстрелить себе в ногу при длинных транзакциях
Например, при обмене между базами (не через репликацию)- загружаешь последовательно данные из пришедшего пакета. А в нем данные идут сначала по одной таблице, потом по другой… Тут не обеспечишь на каждой вставке согласованность — только для всей транзакции.
Согласен. Их же не зря придумали и есть случаи, когда использование Defferable оправдано и полезно.
К тому же, при наступлении подобного вашему случая, достаточно указать set constraints all deferred; точно на время подобной вставки. Что будет явно означать, что ожидаются неконсистентные данные, которые можно коммитить только после полной загрузки.

Но. Статья претендует на набор граблей/хороших практик и «как надо, а как не надо делать», а в ней написаны достаточно спорные вещи. Отношение к Deferrable тому пример.
Или рекомендация использовать With. Что тоже совсем не полезно для запросов. Ниже об этом уже написали.
Или «Боль! Перед тем, как написать delete или update, напишите where»
гораздо полезнее писать SET AUTOCOMMIT OFF! Всегда!
Потому что только это позволит оценить последствия до их применения. Хотя бы по количеству удаленных записей.

Плохо учить падаванов спорным практикам. Их приходится потом мучительно переучивать.
В остальном пункты здравые, спасибо автору за статью. Я себе занес в список ссылок, который стоит показывать разработчикам :)
Я внес замечания в статью по поводу with, deferrable и set autocommit off. Спасибо большое за замечания и советы.
Боль! Перед тем, как написать delete или update, напишите where

Я select пишу.

Никогда нельзя перенаправлять клиента с сервера в базу под собственным, уникальным пользователем БД.

На самом деле зависит от задачи. Если изначально клиентов мало, то журналирование производится гораздо проще. Кто, когда с какого ip и т.д. Это моё сугубо личное ИМХО.
Если количество клиентов гарантированно останется небольшим (десяток-другой) и увеличиваться никогда не будет, то да. Главное, не ошибиться.
А можно, если не сложно, на 14й пункт какой-нибудь простой пример.
Что именно за функции имеются в виду?
Что именно за функции имеются в виду?

предполагаю, что имеются ввиду функции с категориями изменчивости volatile (по умолчанию) и stable. в случае использования категории immutable с постоянными аргументами функция может быть выполнена всего один раз.


подробнее можно почитать здесь.

Это необходимо не только для восстановления при сбоях, но и дает много интересных возможностей разработчикам для работы в определенных временных срезах базы. В PostgreSQL для этого есть barman.

Если у вас нагруженная БД то хранение WAL для PITR это боль. Кроме того создание инкрементального бекапа при помощи braman это отдельная боль (если у вас БД больше 100 гигов). Большую часть этих проблем я решаю тут pg_arman .

Кроме того создание инкрементального бекапа при помощи braman это отдельная боль (если у вас БД больше 100 гигов)

А можно поподробнее про подводные камни на 100 ГБ? У меня БД на 60 ГБ, хочу узнать, к чему готовиться через пару лет.

Для того что бы создать инкремент нужно вычитать ВСЮ бд т.е. прочитать каждую страницу и сверить её LSN.
Чем больше БД тем дольше занимает этот процесс. ptrack умеет отслеживать изменения памяти на лету с почти нулевым оверхедом (1-2%), а pg_arman умеет читать эту информации для того, что бы без каких либо лишних движений делать бекап.

Используйте «with», с ним код становится чище и его можно читать сверху вниз, а не петлять среди блоков join'ов.

Только оптимизатор Постгреса (в отличие от Оракла) не умеет заглядывать за «with», это для него как отдельный запрос, так что такое разбиение может (и скорее всего будет) работать существенно медленнее исходного запроса.


Если можете написать запрос без временных таблиц — не раздумывайте и напишите! Обычно CTE, создаваемое конструкцией «with», является приемлемой альтернативой. Дело в том, что PostgreSQL для каждой временной таблицы создает временный файл…

А какая база делает иначе? Как СУБД может предугадать сколько данных в таблице будет? Вроде логично всё. Не перепутаны ли тут временные таблицы с временными вьхами?

Sign up to leave a comment.

Articles