в postgresql более эффективны разделы или несколько баз данных? - PullRequest
6 голосов
/ 08 декабря 2011

есть приложение, в котором многие компании публикуют информацию.данные каждой компании являются самодостаточными - данные не перекрываются.

с точки зрения производительности, лучше:

  • сохранить идентификатор компании в каждой строке каждой таблицы икаждый индекс использует его?
  • разделите каждую таблицу в соответствии с разделом ID компании
  • и создайте пользователя для доступа к каждой компании для обеспечения безопасности
  • создайте несколько баз данных, одну длякаждая компания

веб-приложение с постоянными соединениями.

мои мысли:

  • новые pg-соединения дороги, поэтому одна база данных создает меньше новыхСоединения
  • , имеющие только одну копию словаря, кажутся более эффективными, чем 200 или около того
  • Несколько баз данных, безусловно, защищены от ошибки программиста
  • , если спецификации приложения должны измениться, чтобы компании делилисьнесколько баз данных будет трудно реализовать

1 Ответ

15 голосов
/ 09 декабря 2011

Я бы порекомендовал поискать информацию в списках рассылки PostgreSQL о мультитенантном дизайне. Там было много дискуссий, и ответ сводится к «это зависит». Между гарантированной изоляцией, производительностью и ремонтопригодностью всегда есть компромиссы.

Общий подход заключается в использовании одной базы данных, но одна схема (пространство имен) для каждого клиента с одинаковой структурой таблиц в каждой схеме, плюс общая или общая схема для данных, которые одинаковы для всех их. Схема PostgreSQL похожа на «базу данных» MySQL, в которой вы можете выполнять запросы по разным схемам, но по умолчанию они изолированы. С данными клиента в отдельной схеме вы можете использовать настройку search_path, обычно через ALTER USER customername SET search_path = 'customerschema, sharedschema', чтобы каждый клиент видел свои данные и только свои данные.

Для дополнительной защиты вам следует REVOKE ALL FROM SCHEMA customerschema FROM public, затем GRANTALL ON SCHEMA customerschema TO thecustomer, поэтому они единственные, кто имеет к нему доступ, и делает то же самое. к каждому из их столов. Ваш пул подключений затем может войти в систему с фиксированной учетной записью пользователя, которая имеет нет GRANT ed доступа к любой схеме клиента, но имеет право на SET ROLE, чтобы стать любым клиентом. (Сделайте это, предоставив им членство в каждой роли клиента с набором NOINHERIT, чтобы права были явно заявлены через SET ROLE). Подключение должно быть немедленно SET ROLE к клиенту, с которым он работает в данный момент. Это позволит вам избежать накладных расходов на создание новых подключений для каждого клиента при сохранении надежной защиты от ошибок программиста, ведущих к доступу к неправильным данным клиента. До тех пор, пока пул выполняет DISCARD ALL и / или RESET ROLE перед передачей соединений следующему клиенту, это обеспечит вам очень сильную изоляцию без разочарования индивидуальные подключения для каждого пользователя.

Если в среде вашего веб-приложения нет приличного встроенного пула соединений (скажем, вы используете PHP с постоянными соединениями), тогда вам действительно нужно создать хороший пул соединений В любом случае находится между Pg и веб-сервером, поскольку слишком большое количество подключений к бэкэнду ухудшит вашу производительность. PgBouncer и PgPool-II являются лучшими вариантами, и они легко могут позаботиться о выполнении для вас DISCARD ALL и RESET ROLE во время передачи соединения.

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

Идеальным подходом, вероятно, будут отдельные таблицы с автоматической безопасностью на уровне строк, контролирующей видимость кортежа, но, к сожалению, в PostgreSQL этого пока нет. Похоже, что он в пути благодаря работе SEPostgreSQL, добавляющей подходящую инфраструктуру и API, но его нет в 9.1.

...