PostgreSQL: Czy lepiej jest używać wielu baz danych z jednym schematem, czy jednej bazy danych z wieloma schematami?

147

Po tym komentarzu do jednego z moich pytań zastanawiam się, czy lepiej jest używać jednej bazy danych ze schematami X, czy odwrotnie.

Moja sytuacja: tworzę aplikację internetową, w której podczas rejestracji tworzę (właściwie) bazę danych (nie, to nie jest sieć społecznościowa: każdy musi mieć dostęp do swoich danych i nigdy nie widzieć danych innego użytkownika) .

W ten sposób korzystałem z poprzedniej wersji mojej aplikacji (która nadal działa na MySQL): za pośrednictwem Plesk API, przy każdej rejestracji wykonuję:

  1. Utwórz użytkownika bazy danych z ograniczonymi uprawnieniami;
  2. Utwórz bazę danych, do której będzie miał dostęp tylko poprzednio utworzony użytkownik i superużytkownik (w celu konserwacji)
  3. Wypełnij bazę danych

Teraz muszę zrobić to samo z PostgreSQL (projekt dojrzewa, a MySQL ... nie spełnia wszystkich potrzeb).

Muszę mieć niezależne kopie zapasowe wszystkich baz danych / schematów: pg_dump działa doskonale w obie strony i to samo dla użytkowników, których można skonfigurować tak, aby mieli dostęp tylko do jednego schematu lub jednej bazy danych.

Więc zakładając, że jesteś bardziej doświadczonymi użytkownikami PostgreSQL niż ja, jakie myślisz, że jest najlepsze rozwiązanie w mojej sytuacji i dlaczego?

Czy wystąpią różnice w wydajności przy korzystaniu z bazy danych $ x zamiast schematów $ x? A jakie rozwiązanie będzie lepsze w przyszłości (niezawodność)?

Wszystkie moje bazy danych / schematy będą zawsze miały tę samą strukturę!

W przypadku tworzenia kopii zapasowych (przy użyciu pg_dump), może lepiej jest użyć jednej bazy danych i wielu schematów, zrzucenie wszystkich schematów naraz: odzyskiwanie będzie dość proste, załadowanie głównego zrzutu na maszynę programistyczną, a następnie zrzucenie i przywrócenie tylko potrzebnego schematu: tam to jeden dodatkowy krok, ale zrzucanie wszystkich schematów wydaje się szybsze niż zrzucanie ich jeden po drugim.

UPDATE 2012

Cóż, struktura i projekt aplikacji bardzo się zmieniły w ciągu ostatnich dwóch lat. Nadal stosuję to one db with many schemaspodejście, ale nadal mam jedną bazę danych dla każdej wersji mojej aplikacji:

Db myapp_01
    \_ my_customer_foo_schema
    \_ my_customer_bar_schema
Db myapp_02
    \_ my_customer_foo_schema
    \_ my_customer_bar_schema

W przypadku kopii zapasowych regularnie zrzucam każdą bazę danych, a następnie przenoszę kopie zapasowe na serwer deweloperski.

Używam też kopii zapasowej PITR / WAL, ale jak powiedziałem wcześniej, nie jest prawdopodobne, że będę musiał przywracać całą bazę danych naraz ... więc prawdopodobnie zostanie odrzucona w tym roku (w mojej sytuacji nie jest to najlepsze podejście ).

Podejście jeden-db-wiele-schematów działało bardzo dobrze od teraz, nawet jeśli struktura aplikacji została całkowicie zmieniona:

Prawie zapomniałem: wszystkie moje bazy danych / schematy będą zawsze miały tę samą strukturę!

... teraz każdy schemat ma własną strukturę, która zmienia się dynamicznie w odpowiedzi na przepływ danych użytkowników.

Strae
źródło
„wszystkie moje bazy danych / schematy będą miały zawsze taką samą strukturę!” masz na myśli to, że wszystkie mają taką samą strukturę? Albo nigdy?
Osama Al-Maadeed
Przepraszam, tak, wszystkie mają tę samą strukturę na zawsze: jeśli zmienię jedną, zmienię je wszystkie;)
Strae
Jeśli masz 1000 klientów, to znaczy, że musisz zaktualizować schemat 1000?
Joshua Partogi
@jpartogi: tak, ale muszę zaktualizować tylko strukturę tabel, a nie dane.
Strae
Więc po co w końcu się zdecydowałeś? Jedno pytanie, chociaż wydajność zapytań itp. Może być kontrolowana przez obszary tabel, schematy skutkujące równoważną wydajnością multi-db vs multi-schema, jakikolwiek wpływ na logi WAL ???
Kapil

Odpowiedzi:

113

„Schemat” PostgreSQL jest mniej więcej taki sam, jak „baza danych” MySQL. Posiadanie wielu baz danych w instalacji PostgreSQL może być problematyczne; posiadanie wielu schematów będzie działać bez problemów. Dlatego na pewno chcesz korzystać z jednej bazy danych i wielu schematów w tej bazie danych.

kquinn
źródło
33
To. Postgres nie pozwala na przeszukiwanie baz danych, co może być dość denerwujące.
mat b
81
„Posiadanie wielu baz danych w instalacji PostgreSQL może być problematyczne” - proszę wyjaśnić; czy jest to problematyczne ogólnie, czy w tym konkretnym przypadku i dlaczego?
akaihola
33
„Najczęstszym przypadkiem użycia wielu schematów w bazie danych jest tworzenie aplikacji typu oprogramowanie jako usługa, w której każdy klient ma swój własny schemat. Chociaż ta technika wydaje się przekonująca, zdecydowanie odradzamy jej stosowanie, ponieważ spowodowała liczne przypadki problemy operacyjne. Na przykład nawet umiarkowana liczba schematów (> 50) może poważnie wpłynąć na wydajność narzędzia Heroku do tworzenia migawek baz danych „ devcenter.heroku.com/articles/heroku-postgresql
Neil McGuigan
16
@NeilMcGuigan: Co ciekawe, wydaje się, że jest to przeciwny wniosek od (zaakceptowanej) odpowiedzi kquinna.
karbokacja
8
Jednak posiadanie jednej bazy danych z wieloma schematami praktycznie uniemożliwia zrzucenie ich jednego schematu. Używam pojedynczej bazy danych postgres z ponad 3000 schematów, a pg_dump po prostu kończy się niepowodzeniem z błędem braku pamięci, jeśli spróbujesz zrzucić pojedynczy schemat. Zastanawiam się, czy byłoby inaczej, gdyby zamiast tego miałbym 3000 baz danych.
Machisuji
27

Zdecydowanie zdecyduję się na podejście jeden-db-wiele-schematów. To pozwala mi zrzucić całą bazę danych, ale bardzo łatwo przywrócić tylko jedną, na wiele sposobów:

  1. Zrzuć bazę danych (cały schemat), załaduj zrzut do nowej bazy danych, zrzuć tylko schemat, którego potrzebuję, i przywróć z powrotem do głównej bazy danych.
  2. Zrzuć schemat osobno, jeden po drugim (ale myślę, że w ten sposób maszyna ucierpi bardziej - i spodziewam się 500 schematów!)

W przeciwnym razie, szukając google, zauważyłem, że nie ma automatycznej procedury do powielenia schematu (używając go jako szablonu), ale wielu sugeruje w ten sposób:

  1. Utwórz szablon-schemat
  2. Kiedy trzeba powielić, zmień jego nazwę na nową
  3. Zrzuć to
  4. Zmień nazwę z powrotem
  5. Przywróć zrzut
  6. Magia jest skończona.

Napisałem dwa wiersze w Pythonie, aby to zrobić; Mam nadzieję, że mogą komuś pomóc (w 2 sekundy napisany kod, nie używaj go w produkcji):

import os
import sys
import pg

# Take the new schema name from the second cmd arguments (the first is the filename)
newSchema = sys.argv[1]

# Temperary folder for the dumps
dumpFile = '/test/dumps/' + str(newSchema) + '.sql'

# Settings
db_name = 'db_name'
db_user = 'db_user'
db_pass = 'db_pass'
schema_as_template = 'schema_name'

# Connection
pgConnect = pg.connect(dbname= db_name, host='localhost', user= db_user, passwd= db_pass)

# Rename schema with the new name
pgConnect.query("ALTER SCHEMA " + schema_as_template + " RENAME TO " + str(newSchema))

# Dump it
command = 'export PGPASSWORD="' + db_pass + '" && pg_dump -U ' + db_user + ' -n ' + str(newSchema) + ' ' + db_name + ' > ' + dumpFile
os.system(command)

# Rename back with its default name
pgConnect.query("ALTER SCHEMA " + str(newSchema) + " RENAME TO " + schema_as_template)

# Restore the previous dump to create the new schema
restore = 'export PGPASSWORD="' + db_pass + '" && psql -U ' + db_user + ' -d ' + db_name + ' < ' + dumpFile
os.system(restore)

# Want to delete the dump file?
os.remove(dumpFile)

# Close connection
pgConnect.close()
Strae
źródło
14

Powiedziałbym, idź z wieloma bazami danych ORAZ wieloma schematami :)

Schematy w PostgreSQL są bardzo podobne do pakietów w Oracle, o ile je znasz. Bazy danych mają na celu rozróżnianie całych zestawów danych, podczas gdy schematy bardziej przypominają jednostki danych.

Na przykład, możesz mieć jedną bazę danych dla całej aplikacji ze schematami „Zarządzanie użytkownikami”, „LongTermStorage” i tak dalej. „Zarządzanie użytkownikami” zawierałoby wówczas tabelę „Użytkownik”, a także wszystkie procedury składowane, wyzwalacze, sekwencje itp., Które są potrzebne do zarządzania użytkownikami.

Bazy danych to całe programy, schematy to komponenty.

Peter Mortensen
źródło
4
... a więc będę miał 1 bazę danych, zawierającą schematy: $ customer1_user_schema, $ customer2_user_schema, $ customer3_user_schema, $ customer1_documents_schema, $ customer2_documents_schema, $ customer3_documents_schema? Mh ... nie wydaje się niezawodnym sposobem ... a co z wydajnością? A co z kodem mojej aplikacji (będzie to php i python)? tak wiele schematów ...
Strae
7
@Strae: Czytam to jako: każdy klient ma swoją bazę danych customer1_database, customer2_database, aw ramach tych baz danych masz schemat_użytkownika, schemat_dokumentów.
frankhommers
6

W kontekście PostgreSQL zalecam używanie jednej bazy danych z wieloma schematami, ponieważ można (np.) UNION ALL w schematach, ale nie w bazach danych. Z tego powodu baza danych jest naprawdę całkowicie izolowana od innej bazy danych, podczas gdy schematy nie są izolowane od innych schematów w tej samej bazie danych.

Jeśli z jakiegoś powodu będziesz musiał w przyszłości konsolidować dane ze schematów, łatwo będzie to zrobić w wielu schematach. W przypadku wielu baz danych potrzeba wielu połączeń db oraz zbierania i łączenia danych z każdej bazy danych „ręcznie” za pomocą logiki aplikacji.

Te ostatnie mają zalety w niektórych przypadkach, ale w większości uważam, że podejście z jedną bazą danych i wieloma schematami jest bardziej przydatne.

emax
źródło
4

Szereg schematów powinno być lżejszych niż wiele baz danych, chociaż nie mogę znaleźć odniesienia, które to potwierdza.

Ale jeśli naprawdę chcesz zachować oddzielne rzeczy (zamiast refaktoryzować aplikację internetową, tak aby kolumna „customer” była dodawana do twoich tabel), możesz nadal chcieć używać oddzielnych baz danych: zapewniam, że możesz łatwiej przywracać w ten sposób baza danych konkretnego klienta - bez przeszkadzania innym klientom.

Troels Arvin
źródło