Partitionieren oder nicht partitionieren?


8

Nachdem ich bereits mehrere Fragen zu SO, externen Blog-Posts und Handbuch gelesen habe

Ich frage mich immer noch, ob ich in Anbetracht meines Falls mit der Partitionierung beginnen soll oder nicht.

Der Fall - vereinfacht

Kundendaten speichern. Alle Namen der unten genannten Tabellen dienen der Übersichtlichkeit.

  1. Objekte haben, die vom Kunden identifiziert werden können und nicht physische Wesen sind, auch ihre physischen Objekte, in denen sie tatsächlich gespeichert sind, falls einige Objekte bei Bedarf an den Kunden zurückgesendet oder auf andere Weise verarbeitet werden müssen. Sie werden in einer Viele-zu-Viele-Beziehung abgebildet. objects_nonphysical, objects_physical, objects_mapping_table.

  2. Die zweite Viele-zu-Viele-Beziehung besteht zwischen diesen nicht-physischen Objekten und ihren Metriken. Es gibt Objekte, die an einige Metriken gebunden sind. metrics,metrics_objects_nonphysical

  3. Sowohl nicht-physische als auch physische Objekte haben ihre Hierarchietabellen, die Kind-Eltern-Beziehungen sind. objects_nonphysical_hierarchy,objects_physical_hierarchy

Abhängig von den Bedürfnissen und Anforderungen jedes Kunden können die Daten zu physischen Objekten bereitgestellt werden oder müssen möglicherweise von Grund auf neu erstellt werden. Grundsätzlich muss ich Folgendes tun:

  • Pflegen Sie das interne System für schnelle INSERTund SELECTAnweisungen, da hier das Mapping stattfinden wird.

  • Warten Sie das System, damit externe Kunden ihre nicht-physischen Objekte anzeigen und bearbeiten können - schnelles Abrufen von Daten. Starkes Bedürfnis nach Effizienz für SELECTAussagen - diese Daten stehen vielen Kunden zur Verfügung, wann immer sie wollen.

Meine Überlegung

Es kann einen Kunden geben, der auf die Daten zugreifen, sie anzeigen und bearbeiten kann, aber das muss kein Auftragnehmer sein, von dem wir die Daten erhalten haben / für den wir die Daten verarbeiten.

Dies hat mich veranlasst, die Tabellenpartitionierung in mein System einzuführen, da ich immer weiß, in welche Partitionsdaten ich fallen soll ( Partitionierung für Auftragnehmer ), und dann das System für externe Kunden zu pflegen, bei denen ich eine Partitionierung für Kunden benötige (dies würde bei einigen der Fall sein) Verzögern Sie die Verwendung von Automatisierungstools und Regelsätzen, um die Daten auf Kundenart neu zu schreiben, sodass wir für jeden Kunden nur eine Partition für jede Tabelle scannen.

Datenvolumen

Meine Daten werden ständig wachsen, insbesondere beim Importieren von Objekten und Metriken neuer Kunden. Das Tempo, mit dem neue Daten in das System gelangen, ist derzeit auf lange Sicht nicht vorhersehbar. Es gibt wirklich keine Möglichkeit, dies zu messen, wenn man nicht weiß, wer der nächste Kunde sein wird. Derzeit gibt es nur 2 Kunden mit mehr oder weniger 1 Million Zeilen für jeden Kunden in jeder Tabelle. Aber in Zukunft gehe ich davon aus, dass neue Kunden auch ein Volumen von etwa 10 Millionen Zeilen haben werden.

Fragen

Diese Fragen hängen alle miteinander zusammen.

  1. Sollte Partitionierung hier wirklich in Betracht gezogen werden, oder ist das ein Overkill? Ich halte es für nützlich, da ich immer genau eine Partition scanne.
  2. Wenn Partitionierung der richtige Weg ist, wie kann ich FKEinschränkungen unter Berücksichtigung meiner Anforderungen am effektivsten durchsetzen ? Soll ich mich dafür entscheiden constraint triggersoder es einfach in der Anwendungsschicht für das interne System behalten oder vielleicht eine andere Methode?
  3. Wenn Partitionierung nicht der richtige Weg ist, worauf sollte ich eingehen?

Wenn nicht genügend Daten bereitgestellt werden, lassen Sie es mich bitte in den Kommentaren unten wissen.



3
Im Allgemeinen wird empfohlen, die Produktion ohne Overhead von Indizes, Partitionen usw. zu starten und dann bei Bedarf Indizes und Partitionen usw. hinzuzufügen
Alonk

1
Mit der Partitionierung erhalten Sie nur Beschleunigungen für bestimmte Arten von Abfragen, während Sie andere Arten von Abfragen treffen. Sie werden auch einen Treffer bei Schreibvorgängen erzielen. Partitionierung sollte nicht das erste sein, wonach Sie greifen, und ich denke, Sie werden auf absehbare Zeit problemlos einfache Indizes verwenden und diese Brücken überqueren können, wenn Sie zu ihnen gelangen. 5 Millionen Zeilen sind nicht so groß. Dies könnte ein nützlicher Blog mit Geschwindigkeitsvergleichen sein: if-not-true-then-false.com/2009/…
Dizzystar

2
Ich stimme Dizzystar zu, ich würde mich jetzt nicht darum kümmern. Überqueren Sie diese Brücke, wenn Sie sie erreichen. Derzeit macht es die Partitionierung in Postgres auch schwierig (wenn nicht unmöglich), geeignete Fremdschlüssel zu verwenden (dies kann sich mit 9.7 ändern, aber es ist noch nichts festgelegt). Selbst eine Tabelle mit 50 Millionen Zeilen ist nicht unbedingt ein Kandidat für die Partitionierung. Wenn Ihre Abfragen hauptsächlich Gleichheitsbedingungen haben, die die Anzahl der Zeilen erheblich reduzieren, können Sie durch eine gute Indizierung einen langen Weg zurücklegen.
a_horse_with_no_name

1
Für mich ist nicht wirklich klar, was Sie unter "Partitionierung für Auftragnehmer" verstehen. Unterscheiden sich die von Auftragnehmern verwendeten Tabellen von denen eines Kunden? Kommt es jemals vor, dass Kunde A auf die Daten von Kunde B zugreifen muss? Wenn nicht, kann die Trennung kundenspezifischer Daten in ein Kundenschema ein guter Weg sein - aber nicht unbedingt für die Leistung, sondern für die Trennung von Bedenken (erhöhte Sicherheit / Datenschutz usw.).
Dekso

Antworten:


1

Ihre Frage hat viele offene Fragen, aber die Partitionierung nach Kunden könnte der richtige Weg sein - insbesondere, wenn:

  • Sie erwarten viele Kunden,
  • Jeder von ihnen könnte Tonnen von Daten haben ("Tonnen" bedeutet viel mehr als RAM-Cache-Größe),
  • Die meisten ihrer Datensätze schließen sich gegenseitig aus (jeder Kunde sieht unterschiedliche Teilmengen von Daten).

REGELN oder Trigger sind ein Leistungsaufwand und können vermieden werden.

Betrachten Sie etwas in diese Richtung:

BEGIN;

CREATE USER tenant1;
CREATE USER tenant2;

CREATE SCHEMA app;
CREATE SCHEMA tenant1;
CREATE SCHEMA tenant2;

CREATE TABLE app.objects_nonphysical(id int);
CREATE TABLE app.objects_physical(id int);
CREATE TABLE app.objects_mapping(id int);    
CREATE TABLE tenant1.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant1.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant1.objects_mapping() INHERITS(app.objects_mapping);
CREATE TABLE tenant2.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant2.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant2.objects_mapping() INHERITS(app.objects_mapping);

GRANT USAGE ON SCHEMA tenant1 TO tenant1;
GRANT USAGE ON SCHEMA tenant2 TO tenant2;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant1 TO tenant1;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant2 TO tenant2;

/* TEST: simulate login as customer */
SET SESSION AUTHORIZATION tenant2;
/* No schema needed - default search_path works */
SELECT count(*) FROM objects_nonphysical; 

ROLLBACK;

Sie benötigen keine Trigger / Regeln, um es zu pflegen.

Hier gibt es offene Enden - das ist nur ein Entwurf ... Einige Probleme:

  • PK, FK und Indizes werden nicht "vererbt".
  • Selbst wenn Sie sie erstellen, wird die PK in der Mastertabelle nicht erzwungen
  • Sie können dies überwinden, indem Sie für alle Mandanten dieselbe Reihenfolge verwenden
  • Natürlich muss die Anwendung für dieses Modell angepasst werden

0

Es tut nicht weh, wenn Sie jetzt die Partitionierung implementieren, sondern eine einzelne Partition verwenden, bis Ihr System wirklich eine neue benötigt. In Bezug auf die Leistung wird es nur einen winzigen Aufwand geben, um mit Primärschlüsseln und dergleichen umzugehen.

Ich empfehle, Regeln für die Umleitung von Einfügungen und eine externe Tabelle für die Primärschlüssel zu verwenden (z. B. CREATE TABLE objects_physical_ids (id bigserial NOT NULL PRIMARY KEY)zusammen mit einem Funktionsauslöser, der eine Zeile in die IDs-Tabelle einfügt und in NEW.id kopiert (z. B. INSERT INTO objects_physical_ids DEFAULT VALUES RETURNING id INTO NEW.id;), und anderen Auslösern, die sich mit dem Löschen befassen und Aktualisierungen sowie ein Trigger, der diese Funktionsauslöser für jede geerbte Tabelle ausführt (vergessen Sie nicht, dies zu tun, wenn Sie eine neue geerbte Tabelle erstellen!). Dann können alle zugehörigen Tabellen eine FOREIGN KEYzu der entsprechenden IDs-Tabelle haben (einschließlich aller Fremdschlüsselaktionen wie ON UPDATEoder ON DELETE).


2
Die Regeln und Auslöser haben definitiv Overhead und es ist einfach zu messen. Darüber hinaus erhöhen sie die Komplexität und erschweren das Debuggen (viel). Nachdem ich mehrmals auf diese Weise vorgegangen bin, würde ich vorschlagen (ohne zugegebenermaßen alle Details zu kennen), eine leere übergeordnete Tabelle und eine oder mehrere untergeordnete Partitionen beizubehalten. Wenn Sie das Partitionierungsschema ändern, kann dies sehr praktisch sein.
Dekso
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.