Benötige ich einen Primärschlüssel für meine Tabelle, die eine UNIQUE (zusammengesetzte 4-Spalten) hat, von denen eine NULL sein kann?

8

Ich habe die folgende Tabelle (PostgreSQL 8.3), die Preise einiger Produkte speichert. Die Preise sind mit einer anderen Datenbank synchronisiert, im Grunde werden die meisten der folgenden Felder (abgesehen von einem) nicht von unserem Kunden aktualisiert - sondern stattdessen ab und wieder aktualisiert und mit einer anderen Lagerdatenbank synchronisiert:

%Vor%

Bei der Synchronisation lösche ich die meisten der oben genannten Daten, mit Ausnahme der Daten, für die my_custom_field TRUE ist (wenn der Wert TRUE ist, bedeutet dies, dass der Client dieses Feld über seinen CMS aktualisiert hat und dieser Datensatz daher nicht gelöscht werden sollte). Ich fügt dann 100s bis 1000s Zeilen in die Tabelle ein, und UPDATE, wo die INSERT fehlschlägt (d. H. Wo die Kombination von (template_sku, siteid, currencyid, colourid) bereits existiert).

Meine Frage ist - welche Best Practice sollte hier angewendet werden, um einen Primärschlüssel zu erstellen? Wird ein Primärschlüssel benötigt? Ich wollte den Primärschlüssel = (template_sku, siteid, currencyid, colourid) machen - aber das colourid-Feld kann NULL sein, und die Verwendung in einem zusammengesetzten Primärschlüssel ist nicht möglich.

Nach dem, was ich in anderen Forenbeiträgen gelesen habe, denke ich, dass ich das oben Gesagte richtig gemacht habe und nur klarstellen muss:

1) Sollte ich einen "seriellen" Primärschlüssel verwenden, nur für den Fall, dass ich jemals einen brauche? Im Moment tue ich das nicht und werde es auch nicht tun, denn die wichtigen Daten in der Tabelle sind der Preis und mein benutzerdefiniertes Feld, die nur durch die Kombination (template_sku, siteid, currencyid, colourid) identifiziert werden.

>

2) Da (template_sku, siteeid, currencyid, colourid) die Kombination ist, die ich verwenden werde, um den Preis eines Produkts abzufragen, sollte ich meinen Spalten weitere Indizierung hinzufügen, wie zum Beispiel "template_sku", das ein varchar ist? Oder ist die UNIQUE-Einschränkung bereits ein guter Index für meine SELECTs?

    
rishijd 09.05.2012, 12:59
quelle

1 Antwort

10
  

Soll ich einen "seriellen" Primärschlüssel verwenden, nur für den Fall, dass ich je einen brauche?

Sie können später problemlos eine serielle Spalte hinzufügen, wenn Sie eine benötigen:

%Vor%

Die Spalte wird automatisch mit eindeutigen Werten gefüllt. Sie können es sogar zum Primärschlüssel in derselben Anweisung machen (wenn noch kein Primärschlüssel definiert ist):

%Vor%

Wenn Sie die Tabelle aus anderen Tabellen referenzieren, rate ich Ihnen, einen solchen Ersatz-Primärschlüssel zu verwenden, da es ziemlich unhandlich ist, ihn durch vier Spalten zu verknüpfen. Es ist auch langsamer in SELECTs mit JOINs.

In beiden Fällen sollten Sie einen Primärschlüssel definieren . Der UNIQUE-Index mit einer Nullwert-Spalte ist kein vollständiger Ersatz. Es erlaubt Duplikate für Kombinationen, die einen NULL-Wert enthalten, da zwei NULL-Werte niemals als gleich betrachtet werden. Dies kann zu Problemen führen.

Wie

  

Das Farbfeld kann NULL sein

Sie möchten möglicherweise zwei eindeutige Indizes erstellen. Die Kombination (template_sku, siteid, currencyid, colourid) darf wegen der Nullable PRIMARY KEY keine colourid sein, aber Sie können eine UNIQUE Einschränkung erstellen, wie Sie sie bereits haben (indem Sie automatisch einen Index implementieren):

%Vor%

Dieser Index deckt perfekt die Fragen ab, die Sie in 2) erwähnt haben.
Erstellen Sie zusätzlich einen partiellen eindeutigen Index, wenn Sie "Duplikate" mit (colourid IS NULL) vermeiden wollen:

%Vor%

Um alle Grundlagen abzudecken. Ich habe mehr über diese Technik in einer ähnlichen Antwort auf dba.SE geschrieben.

Die einfache Alternative zum obigen Beispiel besteht darin, colourid NOT NULL zu machen und einen Primärschlüssel anstelle des obigen product_pricebands_uni_idx zu erstellen.

Auch, wie Sie

  

lösche grundsätzlich die meisten Daten

Bei der Nachfüllung wird es schneller möglich sein, Indizes, die während des Nachfüllvorgangs nicht benötigt sind, zu löschen und diese anschließend neu zu erstellen. Es ist um eine Größenordnung schneller, einen Index von Grund auf neu zu erstellen, als alle Zeilen inkrementell hinzuzufügen.

Woher wissen Sie, welche Indizes verwendet werden (benötigt)?

  • Testen Sie Ihre Abfragen mit EXPLAIN ANALYZE .
  • Oder verwenden Sie die integrierten Statistiken . pgAdmin zeigt Statistiken auf einer separaten Registerkarte für das ausgewählte Objekt an.

Es kann auch schneller sein, die wenigen Zeilen mit my_custom_field = TRUE in einer temporären Tabelle auszuwählen, TRUNCATE die Basistabelle und INSERT die Überlebenden. Hängt davon ab, ob Sie Fremdschlüssel definiert haben. Würde so aussehen:

%Vor%

Dies vermeidet viel Staubsaugen.

    
Erwin Brandstetter 09.05.2012, 14:32
quelle