Grundsatzfrage Primary Key

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
zappa2
Beiträge: 15
Registriert: Fr 5. Okt 2018, 10:59

Ich habe mal auf einer DB-Konferenz aufgeschnappt, dass ein PK IMMER ein Integer bzw. BigInt sein soll. Wenn man zusammengesetzte Keys benötigt, daraus einfach ein Unique-Constraint machen. Jetzt habe ich eine gegenteilige Meinung gehört, dass aus Geschwindigkeitsgründen der zusammengesetzte Unique als PK benutzt werden muss.
Dabei kommen Konstrukte vor, dass z.B. 3 Char(30) und diverse Integer zusammen einen PK darstellen. Mir sieht das ziemlich schräg aus.
Was stimmt denn nun?
Benutzeravatar
martin.koeditz
Beiträge: 235
Registriert: Sa 31. Mär 2018, 14:35

N'Abend,

du kannst einen Primärschlüssel zusammenbauen wie du möchtest. Die Sinnhaftigkeit ergibt sich aus dem jeweiligen Anwendungsfall.
Aus den jeweiligen Feldern wird ein eindeutiger Hash für jeden Datensatz gebildet. Dieser wird später bei Abfragen genutzt. Dabei ist zunächst egal, ob die Basisfelder Zahlen- oder Texttypen sind.

Ein Primärschlüssel in einer Rechnungstabelle könnte z.B. so aussehen:

Code: Alles auswählen

RECHNUNGSTYP | RECHNUNGSNR | RECHNUNGSDATUM
'ER'         | 'R12345'    | '20.11.2020'
'AR'         | 'R12345'    | '19.11.2020'
 
Hier bilden die Felder RECHNUNGSTYP und RECHNUNGSNR den Primärschlüssel. Die Rechnungsnummer allein ist nicht eindeutig, da diese sowohl in Ein- als auch Ausgangsrechnungen vorkommen kann.
Natürlich kann man auch einen Primärschlüssel als laufende Nummer und einen Unique Key ber den Typ und die Nummer erstellen. Vorteil ist, dass die Fremdschlüssel in den Kindtabellen ebenfalls nur ein Feld benötigen.

Warum werden nun häufig Zahlentypen für Primärschlüssel verwendet? Weil diese weniger Speicher belegen.
Zum Vergleich: Ein INT-Feld hat eine Größe von 32 Bit (4 Byte). Ein Zeichen in einem Varchar-Feld mit UTF-8 hat 2 bis 4 Byte Größe.

Häufig werden noch Fremdschlüssel auf diese Primärschlüssel gebildet. Die Fremdschlüssel benötigen die gleichen Datentypen. Damit kann man sich schnell vorstellen welchen Unterschied die richtige Wahl des Datentyps macht. 1 Byte Größenunterschied bei 1 Mio. Datensätzen sind bereits ein Megabyte.

Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 198
Registriert: Mo 7. Mai 2018, 18:09

In modernen DB-Konzepten gibt es für jede Tabelle eine Identity-Spalte, i.d.R. vom Typ BIGINT. DIese ist somit automatisch "unique not null" und Primary Key, da diese Spalte in Beziehungen wiederum "Foreign Key" sein kann.
Dies ist die schnellste und effektivste Methode Parent/Child-Beziehungen (Auftragskopf/-Position) oder Fremdbeziehungen (z.B. Kunden-Nummer vom Auftrag zum Kundenstamm) zu definieren.

Vollkommen unabhängig davon gibt es natürlich "Compound Keys" die meist auch Unique häufig jedoch nur der schnelleren Abfrage wegen verwendet werden.
Nimmt man den Auftragkopf, so hat dieser einen Unique Key (Mandant, Auftragsnummer) genauso wie die Position mit Mandant/Auftrag/Position.

Viele Frameworks stützen sich ausschließlich auf das Identity-Column-Konzept, da sich damit Direktzugriffe via Update/Delete/Join sehr effizient darstellen lassen.

Der Platzbedarf von Bigint's spielt damit eine wesentliche Rolle, da somit viele Zeilen in einem Block direkt auffinden lassen.

Identity-Columns sind unveränderbar mit einer Information verbunden.
Somit lassen sich Szenarien wie das Ändern von Produktnummern oder Kundennummern nur an Hand einer einzigen Tabelle super schnell realisieren, da diese Stammdatentabelle nie mit ihrem "textuellen" Schlüssel sondern ausschließlich via Identity verknüpft sind.

In meiner langen Zeit als Entwickler (seit dem 1.9.2020 immerhin 45 Jahre) sind mir halt häufiger solche Szenarien begegnet da es immer wieder Zwänge gab, bestimmte Schlüssel neuen Erfordernissen anzupassen.
Ihr glaubt nicht, wie viele Mappingtabellen oder sonstige Verfahren erfunden werden müssen, wenn Schlüssel sich ändern.

Fazit:
Primary Key sollte nach Möglichkeit immer eine Identity-Column sein.
Zusätzliche Indizes oder Contraints sind mit compound Keys ebenso durchaus sinnvoll.
zappa2
Beiträge: 15
Registriert: Fr 5. Okt 2018, 10:59

Vielen Dank für Eure Antworten. Diese geben mir noch einmal sehr gute Argumente in die Hand.
In der Tat gibt es unglaubliche Konstrukte, um die Primary Keys mit mehreren Feldern in andere Tabellen zu kopieren.
Am Augenscheinlichsten ist es m.E. wenn man sieht, in wieviel Tabellen ein Textfeld geändert werden muss, da dieses als PK einer Tabelle zentraler Dreh- und Angelpunkt für viele weitere Tabellen ist. Wieviel einfacher wäre da ein Foreign Key auf einen Integer, der auf das Textfeld zeigt: Änderung des Textfeldes an einer einzigen Stelle -> fertig. Vom Speicherverbrauch gar nicht zu reden.

Also noch mal vielen Dank!
Antworten