Condividere una singola sequenza di chiavi primarie su un database?


14

È una pratica accettabile usare una singola sequenza come chiave primaria su tutte le tabelle (invece che una chiave primaria sia unica per una determinata tabella, è unica per tutte le tabelle)? In tal caso, è oggettivamente meglio dell'utilizzo di una singola sequenza di chiavi primarie tra le tabelle.

Sono uno sviluppatore di software junior, non un DBA, quindi sto ancora imparando molte delle basi di una buona progettazione di database.

Modifica: Nel caso qualcuno si stia chiedendo, di recente ho letto una critica alla progettazione di un database da parte di uno dei DBA della nostra azienda che ha menzionato il fatto che il design non ha utilizzato una singola chiave primaria nell'intero database, che suonava in modo diverso rispetto a quello Ho imparato finora.

Edit2: per rispondere a una domanda nei commenti, questo è per Oracle 11g, ma mi chiedevo a un livello specifico non di database. Se questa domanda dipende dal database, sarei interessato a sapere perché, ma in tal caso cercherò una risposta specifica per Oracle.


2
Di solito è un'idea terribile, per motivi di prestazioni.
Philᵀᴹ

1
In realtà, c'è un vantaggio maggiore nell'avere ogni tabella con un proprio intervallo di chiavi primarie indipendente. Ma solo nel caso in cui guardi un gruppo di ID che potresti dire, questo è Account, quello è PurchaseHeader, ecc. Per fare questo è necessario un po 'di installazione e (come qualsiasi cosa con scopi speciali) un po' di cure e alimentazione in corso. (Sì, ho lavorato con un sistema come questo, molti anni fa.)
RLF,

Quale DBMS stai usando? Oracolo? Postgres? DB2?
a_horse_with_no_name

1
È possibile che tu abbia interpretato male ciò che intendeva dire? Forse non era così letterale?
JamesRyan,

Il DBA dell'azienda ha effettivamente significato che non ci sono campi chiave primaria presenti in nessuna delle tabelle?
Max Vernon,

Risposte:


13

Accettabile? Sicuro. Comune? No. Benefico? Dubbioso.

Nel mio vecchio lavoro abbiamo ereditato un sistema in cui avevano un generatore di sequenza centrale (questo era un sistema SQL Server molto prima che SEQUENCEfosse introdotto in SQL Server 2012). Non è stato davvero un collo di bottiglia nelle prestazioni e non dovrebbe esserlo a meno che non si generino centinaia di migliaia di valori al secondo. Ma ha reso tutto il codice molto più complesso di quanto doveva essere, senza una buona ragione. L'intento del progetto era quello di essere sicuri che se a qualcosa nel sistema fosse assegnato un valore ID di 12, solo una cosa nel sistema poteva avere l'ID 12. Questo mi sembrava abbastanza ottuso e non l'ho mai capito. Se ho un cliente con CustomerID = 12, perché ciò mi impedisce di avere un ordine con OrderID = 12?

Vedo l'utilità di un generatore di sequenza centrale se hai più sistemi e stai generando ID per un certo tipo di entità (ad esempio, un cliente o un ordine) da questi sistemi multipli. Una sequenza centrale può distribuire nuovi valori a più sistemi senza essere un collo di bottiglia (solo un singolo punto di errore) e senza timore che due sistemi generino lo stesso ID.


Se dovessi scegliere tra una cosa del genere e semplicemente usare gli identificativi univoci come chiavi primarie, avresti una preferenza (anche se la risposta è probabilmente "dipende")? Sembra che un GUID possa aggirare il problema allo stesso modo, tranne per il fatto che otterresti un'implementazione standard piuttosto che dover creare il tuo generatore di chiavi primario centralizzato. Ovviamente, l'utilizzo di una sequenza in SQL 2012 compirebbe entrambe le cose, ma supponendo che qualcuno sia su una versione precedente?
SqlRyan,

2
@SqlRyan Dovrei capire perché un OrderID deve essere completamente distinto da un ID cliente. Quasi certamente non userei un GUID per questo; la configurazione delle gamme IDENTITY potrebbe essere migliore (i clienti iniziano da 1, gli ordini iniziano da 1000000, ecc.) con avvisi in atto per quando ti sei avvicinato all'esaurimento della gamma ovviamente.
Aaron Bertrand

1
@SqlRyan: l'utilizzo di un GUID mal implementato come chiave primaria in cluster può causare ogni tipo di problema. Come ha detto Aaron, l'IDENTITÀ si adatta molto meglio allo scopo.
Max Vernon,

In un sistema precedente ho visto l'utilizzo di una singola sequenza nell'intero database, questo è stato fatto per consentire a una chiave esterna di puntare a numerose tabelle diverse anziché a una singola tabella, in modo che quando dicevi che la chiave esterna di due righe diverse erano 12, sapevi che indicavano la stessa cosa senza bisogno di controllare quale possibile tavolo indicassero. Un 13 nella stessa colonna potrebbe potenzialmente essere la chiave primaria su una tabella diversa. Personalmente sono molto a disagio con quello stile di design.
Lawtonfogle,

@AaronBertrand Oppure, in alternativa, utilizzare semplici identificatori di numeri interi e aggiungere un po 'di codice all'inizio quando questi sono rivolti al cliente. per esempio. I1337, C1337 chiaramente una fattura o un cliente
JamesRyan,

7

L'idea ha il merito in un database molto complesso in cui le persone potrebbero accidentalmente unirsi a una tabella usando la colonna sbagliata e ottenere righe non valide solo perché gli ID INT sono gli stessi.

Abbiamo scelto di avere GUID sequenziali come chiavi primarie per evitare alcune trappole della frammentazione dell'Indice dei GUID. Purtroppo sono abbastanza grandi.

Il server SQL può generare GUID sequenziali tramite un valore predefinito che richiama la funzione newSequentialID (), quindi non esiste alcuna tabella di chiavi emesse da mantenere e nessun collo di bottiglia di blocco.

Questo ci ha fornito ID univoci in tutti i database, in tutta la nostra azienda, in quanto sono davvero unici.

Il prezzo ovviamente è lo spazio ed è problematico quando si tenta di trasferire i dati a un data warehouse / cubo in cui la velocità / le dimensioni sono basate sull'uso di chiavi intere più piccole.

Sono convinto che abbiamo evitato molti bug nella nostra app come risultato del loro utilizzo.


4

Non riesco a immaginare quale potrebbe essere la ragione dietro la singola sequenza su tutte le tabelle. Tutto ciò che fa è creare un collo di bottiglia durante la generazione di nuovi valori.

Non importa quanto sia piccolo il sovraccarico di generare valori chiave sequenziali, il generatore è una singola risorsa, il cui accesso deve essere sincronizzato. Più richieste riceve, maggiori sono le possibilità che alcuni richiedenti debbano attendere il loro turno al rubinetto. È ovvio che al singolo generatore di sequenza condiviso tra tutte le tabelle sarà possibile accedere più frequentemente da più client, producendo così più contese rispetto a uno qualsiasi dei generatori multipli. La contesa può diventare più pronunciata se le regole aziendali impongono vincoli ai valori generati, come l'assenza di lacune o ordini rigorosi, o in un database cluster.

Anche con il generatore di sequenze più efficiente ci sarà un carico di lavoro che provoca contese non tollerabili.


2
Potresti voler aggiungere dettagli su come viene creato il collo di bottiglia e perché questa è una cattiva idea.
Max Vernon,

2

lo scopo di PrimaryKey nelle tabelle del database è principalmente quello di imporre l'unicità dei dati che si presume essere univoci, poiché non è possibile coprire tutti i flussi di lavoro e assicurarsi che non comporti la duplicazione dei dati. Il secondo motivo è che molte volte PK è anche il candidato principale per l'indice cluster sulla tabella, quindi aumenta anche il recupero dei dati quando / dove queste colonne sono usate correttamente nella query selezionata.

l'utilizzo di un numero progressivo come chiave primaria è lo stesso di ogni tabella con colonna Identità e solo quella colonna viene utilizzata in PrimaryKey. avere un singolo numero di sequenza nel DB deve avere un uso specifico ma dal punto di vista di PrimaryKey non capisco il motivo. ad esempio in uno dei progetti Datawarehouse a cui ho lavorato, abbiamo Column chiamato LoadBatchID e da ETL a riportare il 50% di tutta la tabella ha questa colonna ma in alcuni punti ha un significato diverso. abbiamo utilizzato l'esclusivo proc come generatore di numeri per assicurarci di non trovare conflitti e anche di aiutarci a risalire al file originale da dove provengono i dati e cosa succede in ogni diversa fase di ETL.


2

Suppongo che una ragione per farlo sarebbe se tutte le entità ereditate da qualche entità madre. Supponiamo, ad esempio, che tu possa essere in grado di inserire un commento su qualsiasi tipo di entità:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Di solito questo non è fatto. .

Non conosco le caratteristiche prestazionali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.