Использовать БД только для складирования данных — это всё равно, что назвать Unix интерфейсом для работы с файлами. Посему, хочу напомнить об известных и не очень функциях БД, которые хотелось бы чаще встречать в боевых веб-приложениях.
tl;dr
Ниже будет про аутентификацию, пользователей, права доступа, целостность данных, FDW, логирование и статистику. Ничего нового.
Примечания
- Буду иметь в виду Ruby on Rails и Postgres, но большинство упоминаний хорошо переносимо на другие языки и СУБД.
- Ничего нового не скажу, всё это давно описано в документации и статьях. Просто хочу ещё раз напомнить об инструментах и о том, куда их можно применить, чтобы жизнь стала немного лучше.
Peer/ident аутентификация
Абсолютно здо́ровская штука, которую почти никто не пользуется. Она мапает пользователя юникса на пользователя БД. В первом случае мапает локального пользователя, а во втором — удалённого. Профит в том, что можно выкинуть из конфига хост, логин и пароль (да и имя БД можно выкинуть), но всё будет работать как раньше. Плюс, будет удобнее заходить в консоль для прямого дебага (просто psql из терминала вместо всех этих -h -U -W -d
и тд).
Документация PG про peer и про ident.
Нюансы: подходит, если у вас не только root и superuser на сервере; а в случае с ident, вы контролируете сеть, железо и уверенны, что там нет засланцев и саботажников.
Примеры использования
Безопасность. Нельзя утащить пароль от БД и подключиться к ней из локального окружения или ещё откуда-либо. Пароля нет и утаскивать нечего.
Разграничение доступа. Если на продакшн или иной сервер есть несколько ролей доступа и они уже разделены на уровне unix-а, то к ним удобно привязать и пользователей БД. В этом случае одна и та же кодовая база будет подключаться под разными пользователями БД. Например, тех.поддержка и разработчики лезут в одну и ту же rails console, но у одних она readonly, а у вторых — полноценная.
Права доступа
В Unix все о них думают и на работу из-под root-а или на 'chmod 777'
очень косо смотрят. А вот в БД всё как-то иначе. Superuser и в путь. Хотя там всё не менее (а может быть даже более) круто.
Там есть иерархия наследования ролей (немного похоже на group в юниксе), там есть доступы разного уровня: к конкретным объектам (вроде прав доступа к файлам), к конкретным операторам (наподобие правил в sudoers
), даже к конкретным строкам. Короче, там всё есть. Пользуйтесь.
Области приложения
В минимальном варианте, вместе с вышеозначенными peer/ident можно разделить пользователя для миграций/деплоя и пользователя для повседневной работы приложения. Это, как минимум, убережёт от вызова DDL в рантайме. Конечно, есть много случаев модификации структуры БД "на горячую". Это и zero-downtime deploy, и разные хотфиксы, и ребилды индексов с concurency (а иногда и без). Но, в общем случае, приложение DDL делать не должно.
Ещё вариант: если у вас "микросервисы", но, почему-то, они пользуются одной БД, то явно разделить доступ к объектам БД — это очень хорошая идея. Ведь интерфейсы взаимодействия должны быть максимально локализованы, а анархический доступ ко всем данным способствует размыванию логики и ответственности.
Ограничение целостности
В Rails 5 хоть как-то началась работа с reference и целостностью данных. Но, в общем случае, многие разработчики считают, что валидации в модели или её окрестностях вполне достаточно для сохранения консистентного состояния данных. Увы, это совсем не так.
Валидации можно пропустить, можно зайти напрямую в БД и навыполнять sql-я, можно при миграции накосячить. В общем, много чего можно сделать. Поэтому всё, на что опирается бизнес-логика должно быть прибито констрейнтами в БД. Это единственный способ сохранить целостность данных и не получить "сюрпризов" при очередном деплое.
Foreign Data Wrapper
Это про подключение одной БД к другой БД, дабы получить доступ к удалённым таблицам как к своим собственным. Главный профит в том, что веб-приложение тут никак не участвует, зато есть много оптимизаций, при работе двух одинаковых БД (вообще, pushdown есть для разных адаптеров, но там всё сложно, поэтому проще считать, что связка PG-PG работает хорошо, а всё остальное — как получится).
Использование FDW
Вместо конфигов с координатами нескольких БД в веб-приложении несравнимо проще оставить одно подключение к БД и разрулить всё на уровне самой БД. Там же, сам собой, решится вопрос прав доступа и выбора объектов, к которым нужен доступ.
Плюс к этому, в будущем можно заменять external table на materialized view или на просто table, но ничего не менять в веб-приложении.
А ещё, можно подключаться к экзотике типа MS Access и исчезают проблемы с ограничениями на использование реляций в моделях. Ведь если у вас 2+ подключения, то джоин двух баз на уровне веб-приложения вы не сделаете, хотя ORM (в частности ActiveRecord) честно попытается это сделать… и отвалится. А на уровне БД это сделать можно, в некоторых случаях, почти без оверхеда.
Логирование
Про него почти все знают и все используют. Но на всякий случай напомню: не стесняйтесь логировать долгие запросы. Из коробки, в PG, оно выключено. Нужно потыкать log_min_duration_statement
. Касаемо его значения есть много холиваров и, возможно, меня запинают, но для начала, поставьте пару секунд. Так как если у вас большое приложение, вы вряд ли это читаете и сами знаете что делать, а если маленькое, то вам некогда разбираться с небольшими тормозами и вас беспокоят только фатальные вещи.
Так же помните про N+1. БД вам про это ничего не скажет. Используйте сторонние инструменты. Например, bullet и здравый смысл.
Статистика
Нужно помнить что она есть и что она может стухнуть. На первых порах всё хорошо. Но со временем, обычно, получается следующее: скорость изменения данных, примерно, одинаковая, а размер таблицы всё больше. Следовательно, vacuum/analyze таблицы начинает происходить всё реже и в какой-то момент планировщик начинает промахиваться. В лучшем случае, запрос попадает в вышеозначенное логирование, в худшем — вы просто страдаете и не понимаете почему. В общем, смотрите в pg_stat_user_tables
и соотносите даты вакуума/аналайза с нагрузкой на таблицы.
А ещё иногда можно использовать статистику для примерного count
. Пригождается редко, но довольно метко, ибо PG не Oracle и count
для всей таблицы выполняется не за O(1), хотя очень хочется.
Конец
Спасибо, что прочитали. Если не сложно, ответьте на вопрос ниже. В свете недавней статьи про GQL вместо SQL он меня начал волновать особенно сильно.
Автор: Loriowar