Ich habe eine Tabelle mit Filmen. Die Felder sind :
id (PK), title, genre, runtime, released_in, tags, origin, downloads
.
Meine Datenbank kann nicht durch doppelte Zeilen verschmutzt werden, daher möchte ich die Eindeutigkeit erzwingen. Das Problem ist, dass verschiedene Filme den gleichen Titel oder sogar die gleichen Felder außer tags
und haben können downloads
. Wie kann man die Einzigartigkeit erzwingen?
Ich dachte an zwei Möglichkeiten:
- Machen Sie alle Felder außer dem
downloads
Primärschlüssel. Ich halte mich zurück,downloads
da es JSON ist und es wahrscheinlich die Leistung beeinflussen wird. - Nur
id
als Primärschlüssel behalten , aber mit allen anderen Spalten eine eindeutige Einschränkung hinzufügen (außer wiederdownloads
).
Ich habe diese Frage gelesen , die sehr ähnlich ist, aber ich habe nicht ganz verstanden, was ich tun soll. Derzeit ist diese Tabelle nicht mit anderen Tabellen verwandt, könnte aber in Zukunft sein.
Im Moment habe ich etwas weniger als 20.000 Datensätze, aber ich erwarte, dass die Zahl wächst. Ich weiß nicht, ob dies für das Thema relevant ist.
BEARBEITEN: Ich habe das Schema geändert und hier ist, wie ich die Tabelle erstellen würde:
CREATE TABLE movies (
id serial PRIMARY KEY,
title text NOT NULL,
runtime smallint NOT NULL CHECK (runtime >= 0),
released_in smallint NOT NULL CHECK (released_in > 0),
genres text[] NOT NULL default ARRAY[]::text[],
tags text[] NOT NULL default ARRAY[]::text[],
origin text[] NOT NULL default ARRAY[]::text[],
downloads json NOT NULL,
inserted_at timestamp NOT NULL default current_timestamp,
CONSTRAINT must_be_unique UNIQUE(title,runtime,released_in,genres,tags,origin)
);
Ich habe auch die timestamp
Spalte hinzugefügt , aber das ist kein Problem, da ich sie nicht berühren werde. So wird es immer automatisch und einzigartig sein.
Antworten:
Ihre Tabellendefinition sieht jetzt überall vernünftig aus. Bei allen Spalten funktioniert
NOT NULL
dieUNIQUE
Einschränkung wie erwartet - mit Ausnahme von Tippfehlern und geringfügigen Unterschieden in der Rechtschreibung, die meiner Meinung nach häufig vorkommen. Betrachten Sie den Kommentar von @ a_horse .Alternative mit funktionalem eindeutigem Index
Die andere Option wäre ein funktionaler eindeutiger Index (ähnlich dem, was @ Dave kommentiert hat ). Ich würde jedoch einen
uuid
Datentyp verwenden, um die Indexgröße und -leistung zu optimieren.Die Umwandlung von Array in Text erfolgt nicht
IMMUTABLE
(aufgrund der generischen Implementierung):Daher benötigen Sie eine kleine Hilfsfunktion , um sie für unveränderlich zu erklären :
Verwenden Sie es für die Indexdefinition:
SQL Fiddle.
Mehr Details:
Sie könnten die generierte UUID als PK verwenden, aber ich würde immer noch die
serial
Spalte mit ihren 4 Bytes verwenden, was für FK-Referenzen und andere Zwecke einfach und billig ist. Eine UUID wäre eine großartige Option für verteilte Systeme, die unabhängig PK-Werte generieren müssen. Oder für sehr große Tische, aber dafür gibt es in unserem Sonnensystem bei weitem nicht genug Filme.Vor-und Nachteile
Eine eindeutige Einschränkung wird mit einem eindeutigen Index für die beteiligten Spalten implementiert. Fügen Sie relevante Spalten zuerst in die Einschränkungsdefinition ein, und Sie haben einen nützlichen Index für andere Zwecke als Sicherheitenvorteil.
Es gibt andere spezifische Vorteile, hier ist eine Liste:
Der funktionale eindeutige Index ist (möglicherweise viel) kleiner, was ihn wesentlich schneller machen kann. Wenn Ihre Spalten nicht zu groß sind, ist der Unterschied nicht groß. Es gibt auch die geringen Gemeinkosten für die Berechnung.
Das Verketten aller Spalten kann zu Fehlalarmen führen (dies
'foo ' || 'bar' = 'foob ' || 'ar'
ist jedoch in diesem Fall sehr unwahrscheinlich. Tippfehler sind so viel wahrscheinlicher, dass Sie sie hier ignorieren können.Einzigartigkeit und Arrays
Arrays müssten konsistent sortiert werden , um in jeder einzigartigen Anordnung, die sich auf den
=
Bediener stützt, Sinn zu machen, weil'{1,2}' <> '{2,1}'
. Ich schlage vor , Look-up - Tabellen fürgenre
,tag
undorigin
mitserial
PK und eindeutigen Einträgen, die für Array - Elemente Fuzzy - Suche ermöglichen. Dann:Implementieren Sie entweder vollständig normalisierte n: m-Beziehungen , die auch referenzielle Integrität bieten. Die Eindeutigkeit jedes Referenzsatzes ist schwieriger festzustellen. Sie können ein
MATERIALIZE VIEW
(MV) mit aggregierten Arrays als Sprungbrett verwenden.oder arbeiten Sie mit sortierten Arrays von FK-Referenzen (die mit FK-Einschränkungen noch nicht unterstützt werden können). Werkzeuge aus dem Zusatzmodul intarray können nützlich sein:
In beiden Fällen kann die Suche mit Arrays direkt oder mit einem normalisierten Schema und einer materialisierten Ansicht mit dem richtigen Index und den richtigen Operatoren sehr effizient sein:
Wenn Sie Postgres 9.4 oder höher verwenden, ziehen Sie
jsonb
stattjson
.quelle
Stellen Sie sich vor, Sie sind mit einer Gruppe von Freunden unterwegs und das Gespräch dreht sich um Filme. Jemand fragt: "Was denkst du über 'Die drei Musketiere'?" Sie antworten: "Welches?"
Welche zusätzlichen Informationen würden Sie benötigen, um absolut sicher zu sein, dass Sie beide an denselben Film denken? Der Name des Regisseurs? Das Produktionsstudio? Das Jahr, in dem es veröffentlicht wurde? Einer der Namen des Sterns? Eine Kombination von zwei oder mehr?
Die Antwort auf meine und Ihre Frage ist dieselbe.
Ich würde jedoch nicht denken, dass das Genre ein guter Kandidat wäre. Ein Grund, Genre ist ein viel zu subjektives Kriterium. Ist "Die drei Musketiere" Aktion? Theater? Abenteuer? Komödie? Action-Abenteuer? romantische Komödie? Ich sehe oft den gleichen Film unter verschiedenen Genres. Selbst wenn Sie mehrere Genres zulassen, kann Ihr Benutzer ein völlig anderes auswählen, das nicht mit dem tatsächlich gesuchten Film aufgeführt ist.
Sogar die Laufzeiten können unterschiedlich sein, insbesondere zwischen Theater- und VCR / DVD / B-Ray-Versionen.
Sie benötigen also harte, objektive Attribute, die sich nicht von einer Medienmitteilung zur nächsten ändern. Leider kann dies den Namen des Films ausschließen, da bekannt ist, dass Filme umbenannt werden, insbesondere nach der Veröffentlichung einer Fortsetzung.
Was ist mit dem Veröffentlichungsdatum? Der Kinostart von 1993? Die VCR-Veröffentlichung von 1999? Die DVD-Veröffentlichung von 2004? Du hast die Idee.
Was ist mit all den Filmen von Alan Smithee? Hat der echte Regisseur jemals endlich einen Schritt nach vorne gemacht, um das Projekt nachträglich zu benennen? Ich weiß es nicht.
Hmm, ich höre besser auf, solange noch einige Kriterien übrig sind.
Einige zusätzliche Punkte:
quelle
Die ID-Spalte hat überhaupt keinen Vorteil, wenn es um die Eindeutigkeit geht, die Sie erzwingen möchten / müssen. Die Eindeutigkeit einer beliebigen Kombination von Attributen wird niemals durch Hinzufügen einer bedeutungslosen ID erzwungen. Sein "Vorteil" zeigt sich nur, wenn Sie jemals an den Punkt gelangen, an dem Sie eine neue Tabelle benötigen, für die ein Fremdschlüssel erforderlich ist. In diesem Fall und wenn Sie die ID aufgenommen haben, können Sie diese als FK in Ihrer neuen Tabelle verwenden. (Aber denken Sie nicht, dass es ein kostenloses Mittagessen sein wird. Der Nachteil eines solchen Ansatzes ist, dass Sie wahrscheinlich mehr Joins schreiben, um Informationen abzurufen, die durchaus Teil dieser neuen Tabelle gewesen sein könnten, die Sie erstellt haben. )
quelle