Cosa ottengono i database relazionali impostando un tipo di dati predefinito per ogni colonna?


44

Sto lavorando con un database SQL in questo momento, e questo mi ha sempre reso curioso, ma le ricerche di Google non aumentano molto: perché i tipi di dati rigorosi?

Capisco perché avresti alcuni tipi di dati diversi, ad esempio come è importante la differenziazione tra dati binari e di testo semplice . Invece di archiviare 1 e 0 di dati binari come testo normale, ora capisco che è più efficiente archiviare i dati binari come proprio formato.

Ma quello che non capisco è quale sia il vantaggio di avere così tanti tipi di dati diversi:

  • Perché mediumtext, longtexte text?
  • Perché decimal, floate int?
  • eccetera.

Qual è il vantaggio di dire al database "Ci saranno solo 256 byte di dati in testo semplice nelle voci di questa colonna". o "Questa colonna può contenere voci di testo fino a 16.777.215 byte"?

È un vantaggio in termini di prestazioni? In tal caso, perché conoscere le dimensioni della voce prima della mano aiuta le prestazioni? O piuttosto è qualcos'altro del tutto?


2
Pensavo che questa domanda dovesse già esistere qui, ma ho cercato nel sito e non ho trovato nulla di utile.
john doe,


6
Se non avete avuto distinte decimal, floate inttipi, che cosa ci si può aspettare 1 / 3di fare? Che dire 1.0 / 3.0? Potresti essere sicuro che quando dividi columnAper columnBquello otterrai i risultati che ti aspetti?
Andrew dice Reintegrare Monica

2
@johndoe Non credo che sarebbe mai stato necessario, ma potrebbe essere molto conveniente. Supponiamo che tu voglia imporre un vincolo che l'inventario di un negozio non può essere inferiore al 5% delle vendite mensili previste. Oppure vuoi assicurarti che il budget totale di ogni divisione non superi il 20% del budget totale. Potrebbe anche apparire in colonne calcolate che si desidera calcolare allo stesso modo in diverse applicazioni utilizzando lo stesso database.
Andrew dice Reintegrare Monica

2
Vale la pena notare che SQLite non imposta un tipo predefinito per colonna : "SQLite è" senza tipo ". Ciò significa che è possibile archiviare qualsiasi tipo di dati desiderato in qualsiasi colonna di qualsiasi tabella, indipendentemente dal tipo di dati dichiarato di quella colonna. "
Prime

Risposte:


50

SQL è un linguaggio di tipo statico . Ciò significa che devi sapere che tipo di variabile (o campo, in questo caso) è prima di poterlo utilizzare. Questo è l'opposto dei linguaggi tipizzati dinamicamente, dove non è necessariamente così.

Fondamentalmente, SQL è progettato per definire i dati ( DDL ) e accedere ai dati ( DML ) in un motore di database relazionale . La tipizzazione statica presenta numerosi vantaggi rispetto alla tipizzazione dinamica di questo tipo di sistema.

  • Gli indici , usati per accedere rapidamente a record specifici, funzionano davvero bene quando le dimensioni sono fisse. Prendi in considerazione una query che utilizza un indice, possibilmente con più campi: se i tipi di dati e le dimensioni sono noti in anticipo, posso confrontare molto rapidamente il mio predicato (clausola WHERE o criteri JOIN) con i valori nell'indice e trovare più rapidamente i record desiderati .

  • Considera due valori interi . In un sistema di tipo dinamico, possono avere dimensioni variabili (pensate a Java BigInteger, o agli interi di precisione arbitraria incorporati di Python). Se voglio confrontare i numeri interi, devo prima conoscere la loro lunghezza in bit. Questo è un aspetto del confronto tra numeri che è in gran parte nascosto dai linguaggi moderni, ma è molto reale a livello di CPU. Se le dimensioni sono fisse e conosciute in anticipo, un intero passaggio viene rimosso dal processo. Ancora una volta, i database dovrebbero essere in grado di elaborare miliardi di transazioni il più rapidamente possibile. La velocità è re.

  • SQL è stato progettato negli anni '70. Nei primi giorni del microcomputer, la memoria era un premio. La limitazione dei dati ha contribuito a mantenere sotto controllo i requisiti di archiviazione. Se un numero intero non supera mai un byte, perché allocare più spazio di archiviazione per esso? Questo è uno spazio sprecato nell'era della memoria limitata. Anche nei tempi moderni, quei byte extra sprecati possono sommare e uccidere le prestazioni della cache di una CPU. Ricorda, questi sono motori di database che potrebbero servire centinaia di transazioni al secondo, non solo il tuo piccolo ambiente di sviluppo.

  • Sulla falsariga di una memoria limitata, è utile poter adattare un singolo record in una singola pagina in memoria. Una volta che vai su una pagina, ci sono più mancate pagine e un accesso alla memoria più lento. I motori più recenti hanno ottimizzazioni per rendere questo meno un problema, ma è ancora lì. Dimensionando i dati in modo appropriato, è possibile mitigare questo rischio.

  • Moreso nei tempi moderni, SQL viene utilizzato per collegarsi ad altre lingue tramite ORM o ODBC o qualche altro livello. Alcune di queste lingue hanno regole sulla necessità di tipi forti e statici. È meglio conformarsi ai requisiti più severi, poiché i linguaggi tipizzati dinamicamente possono gestire i tipi statici più facilmente del contrario.

  • SQL supporta la tipizzazione statica perché i motori di database ne hanno bisogno per le prestazioni, come mostrato sopra.

È interessante notare che esistono implementazioni di SQL che non sono fortemente tipizzate. SQLite è probabilmente l'esempio più popolare di tale motore di database relazionale. Inoltre, è progettato per l'uso a thread singolo su un singolo sistema, quindi i problemi di prestazioni potrebbero non essere così pronunciati come in un database Oracle aziendale che gestisce milioni di richieste al minuto.


SQLite ha tipi di dati che distinguono tra dati numerici e di testo, ma ha solo 5 "classi" di archiviazione dei dati: sqlite.org/datatype3.html
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner Lo so, ma non è ancora così rigoroso come motori come SQL Server, Oracle o PostgreSQL.

SQL non solo è tipizzato staticamente, a causa della presenza di vincoli di controllo, supporta in modo efficace i tipi di perfezionamento.
gardenhead,

4
Sebbene implicito nel primo punto Indexes, più sostanzialmente affermato: avere un tipo di dati consente al motore di database di dare un senso ai dati , fare confronti (numeri più grandi / più piccoli, date / orari precedenti / precedenti, prima / dopo nell'alfabeto), e quindi consente l'ordinamento e l'interrogazione .
Basil Bourque,

Quindi, se le dimensioni sono importanti ... e sql deve sapere in anticipo ... qual è la dimensione esatta di una transazione "Zillion"?
WernerCD,

24

Primo: il testo semplice è binario (non sono nemmeno i caratteri UTF8 o ASCII "0" e "1" ma i bit on / off effettivi)

Detto questo, alcuni dei motivi sono:

  • Vincoli di business / design: consentire il numero 7626355112 nella colonna HEIGHT della tabella PERSON sarebbe errato. Consentire "Howya" nella colonna DATA di una FATTURA sarebbe sbagliato.
  • Meno codice soggetto a errori: non è necessario scrivere codice per assicurarsi che i dati recuperati da una colonna data siano in realtà una data. Se i tipi di colonna fossero dinamici dovresti fare molti controlli del tipo durante la lettura.
  • Efficienza informatica: se una colonna è di tipo INTEGER e SUM (), RDBMS non deve applicare l'aritmetica in virgola mobile.
  • Efficienza di archiviazione: affermando che una colonna è VARCHAR (10) consente all'RDBMS di allocare lo spazio in modo più preciso.
  • Integrità e unicità referenziali: PK (o FK) di una tabella non dovrebbero consentire i float, poiché l'uguaglianza in virgola mobile è complicata, quindi è necessario dichiararli in un tipo non float, come caratteri o numero intero.
  • Esistono RDBMS con tipi di colonna dinamici (non rigorosi) (SQLite) . Utilizza il concetto di "affinità di tipo" pur consentendo di inserire praticamente qualsiasi cosa in qualsiasi colonna senza lamentarsi. Ci sono compromessi che non verranno discussi qui. Vedere questa domanda .

8

È così che il codice sottostante in cui è scritto il database può allocare e usare record di dimensioni fisse, se sa che un campo specifico può contenere da 0 a 256 caratteri di testo, allora può allocare un blocco di 256 byte per memorizzarlo.

Questo rende le cose molto più veloci, ad es. Non è necessario allocare ulteriore memoria mentre l'utente digita, poiché un determinato campo avvia sempre x byte nel record una ricerca o seleziona su quel campo sa controllare sempre x byte in ogni record, ecc.


Se solo tutte le risposte potessero essere così concise e puntuali ...
Darren Ringer,

6

Quando alle colonne di un database vengono assegnati tipi definiti, i tipi vengono generalmente definiti autonomamente per avere una certa dimensione in bit. Di conseguenza:

1) quando il motore di database sta attraversando le righe di una tabella, non deve eseguire alcuna analisi elaborata per determinare dove finisce ogni record, può solo sapere che ogni riga è composta, diciamo, di 32 byte, e quindi per ottenere il il prossimo record è sufficiente aggiungere 32 byte alla posizione del record corrente.

2) quando si cerca un campo all'interno di una riga, è possibile conoscere nuovamente un offset esatto per quel campo senza analizzare nulla, quindi le ricerche di colonne sono una semplice operazione aritmetica piuttosto che un'operazione di elaborazione dei dati potenzialmente costosa.


I campi a lunghezza fissa possono rendere l'elaborazione più efficiente a causa della lunghezza dei record e degli offset dei campi coerenti, ma i campi a lunghezza variabile possono annullare tali vantaggi poiché la lunghezza dei record e l'offset dei campi possono variare. Allo stesso modo, la compressione a livello di record comporterà record a lunghezza variabile, quindi la posizione di un dato record non può essere semplicemente calcolata.
Zenilogix,

Questo è vero ed è stato a lungo un consiglio comune evitare i campi di lunghezza variabile proprio per questo motivo. Non so come lo facciano i grandi giocatori, ma sembra che potresti essere in grado di recuperare alcuni dei vantaggi della lunghezza fissa avendo i campi di larghezza variabile del motore store in una tabella o blocco di memoria non visibile all'utente e avere il la rappresentazione delle tabelle primarie di tali campi deve essere un 'puntatore' (larghezza fissa) al suo interno. Considerando che dovresti fare regolarmente scansioni complete di campi di lunghezza variabile, in primo luogo potrebbe valere la pena di mantenere larghezze fisse per l'hit di prestazioni della direzione indiretta.
UserNotFound,

3

Hai chiesto perché i DBMS hanno tipi di dati statici.

  1. Velocità di ricerca. Il punto centrale di un DBMS è archiviare molti più dati di quanti si possano caricare in un programma. Pensa "tutte le carte di credito generate nel mondo negli ultimi dieci anni". Per cercare in modo efficiente tali dati, sono utili tipi di dati a lunghezza fissa. Ciò è particolarmente vero per i dati strutturati come timbri data e numeri di conto. Se sai con cosa hai a che fare in anticipo, è più facile caricare in indici efficienti.

  2. Integrità e vincoli. È più facile mantenere i dati puliti se ha tipi di dati fissi.

  3. Storia. Gli RDBMS iniziarono quando i computer avevano solo pochi megabyte di RAM e lo spazio di archiviazione su terabyte era enormemente costoso. Il salvataggio di una dozzina di byte in ogni riga di una tabella potrebbe consentire di risparmiare migliaia di dollari e ore di tempo in tali circostanze.

  4. La maledizione della base clienti. Gli RDBMS oggi sono pacchetti software molto complessi, altamente ottimizzati e sono in uso da decenni nell'accumulazione di dati. Sono maturi. Lavorano. Un incidente RDBMS con conseguente perdita di dati su larga scala è al giorno d'oggi rarissimo. Passare a qualcosa con un sistema di tipizzazione dei dati più flessibile non vale il costo o il rischio per la maggior parte delle organizzazioni.

Analogia: può essere palesemente ovvio che i sistemi metropolitani urbani funzionerebbero meglio (più silenziosi, più veloci, più efficienti dal punto di vista energetico) su un binario ferroviario più stretto. Ma come hai intenzione di cambiare tutte le rotaie nel sistema della metropolitana di New York City per realizzare quei miglioramenti? Non lo sei, quindi ottimizzi quello che hai.


3

In generale, più dettagli comunichi al database su ciò che stai archiviando, più può provare a ottimizzare varie metriche delle prestazioni relative a tali dati, come ad esempio quanto spazio da allocare su disco o quanta memoria da allocare al momento del recupero. .

Perché mediumtext, longtext e text?

Non sono sicuro di quale database stai usando, quindi dovrei indovinare: immagino che due di questi tipi di dati abbiano limiti superiori, uno di loro no. L'utilizzo di tipi di dati per il testo con limiti superiori indica al database lo spazio di archiviazione necessario per ciascun record. È anche possibile che alcuni database possano avere modi diversi di memorizzare testo di grandi dimensioni (possibilmente illimitato) rispetto a testo di lunghezza fissa piccola (questo può variare a seconda del database, controlla il tuo manuale per vedere il tuo).

Perché decimale, float e int?

Diversi livelli di precisione richiedono diverse quantità di spazio di archiviazione e non tutti gli usi richiedono i più alti livelli di precisione. Ad esempio, vedere qui: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

Oracle ha un certo numero di diversi tipi numerici con diversi requisiti di archiviazione e diverse capacità in termini di livello di precisione e dimensioni del numero che può essere rappresentato.


2

In una certa misura, è storico.

Una volta, i dati tabulari venivano archiviati in file composti da record a lunghezza fissa a loro volta composti da campi predefiniti in modo tale che un determinato campo fosse sempre dello stesso tipo e nello stesso posto in ogni record. Ciò ha reso l'elaborazione efficiente e ha limitato la complessità della codifica.

Aggiungi alcuni indici a tale file e avrai gli inizi di un database relazionale.

Con l'evoluzione dei database relazionali, hanno iniziato a introdurre più tipi di dati e opzioni di archiviazione, inclusi campi binari o di testo a lunghezza variabile. Ma questo ha introdotto record a lunghezza variabile e ha rotto la capacità di individuare coerentemente i record tramite calcolo o campi tramite un offset fisso. Non importa, le macchine oggi sono molto più potenti di quanto non fossero allora.

A volte è utile impostare una dimensione specifica per un campo per aiutare ad applicare un po 'di logica aziendale, ad esempio 10 cifre per un numero di telefono nordamericano. Gran parte del tempo è solo un po 'di eredità informatica.


1

Se un database utilizza record di dimensioni fisse, qualsiasi record nel database continuerà ad adattarsi, nella stessa posizione, anche se il suo contenuto viene modificato. Al contrario, se un database tenta di archiviare i record utilizzando esattamente la quantità di spazio di archiviazione necessaria per i loro campi, la modifica del nome di Emma Smith in Emma Johnson può comportare che il suo record sia troppo grande per adattarsi alla posizione corrente. Se il record viene spostato in un luogo con spazio sufficiente, qualsiasi indice che tenga traccia di dove si trova dovrebbe essere aggiornato per riflettere la nuova posizione.

Esistono diversi modi per ridurre i costi associati a tali aggiornamenti. Ad esempio, se il sistema mantiene un elenco di numeri di record e posizioni dei dati, tale elenco sarà l'unica cosa che dovrebbe essere aggiornata se si sposta un record. Sfortunatamente, tali approcci hanno ancora costi significativi (ad es. Mantenere una mappatura tra numeri di record e posizioni richiederebbe che il recupero dei record richiederebbe un ulteriore passo per recuperare i dati associati a un determinato numero di record). L'uso di record di dimensioni fisse può sembrare inefficiente, ma rende le cose molto più semplici.


1

Per molto di quello che fai come sviluppatore web, non c'è bisogno di capire cosa sta succedendo "sotto il cofano". Ci sono volte, tuttavia, quando aiuta.

Qual è il vantaggio di dire al database "Ci saranno solo 256 byte di dati in testo semplice nelle voci di questa colonna". o "Questa colonna può contenere voci di testo fino a 16.777.215 byte"?

Come sospetti, il motivo è legato all'efficienza. Le astrazioni perdono . Una query come SELECT author FROM bookspuò essere eseguita abbastanza rapidamente quando sono note le dimensioni di tutti i campi nella tabella.

Come dice Joel,

Come si implementa un database relazionale SELECT author FROM books? In un database relazionale, ogni riga di una tabella (ad es. La tabella dei libri) ha esattamente la stessa lunghezza in byte e ogni campo ha sempre un offset fisso dall'inizio della riga. Quindi, ad esempio, se ogni record nella tabella dei libri è lungo 100 byte e il campo dell'autore è all'offset 23, allora ci sono autori memorizzati nei byte 23, 123, 223, 323, ecc. Qual è il codice in cui spostarsi il prossimo record nel risultato di questa query? Fondamentalmente, è questo:

pointer += 100;

Un'istruzione CPU. Faaaaaaaaaast.

Molte volte, stai lavorando abbastanza lontano dalle basi grintose che non ti devi preoccupare. Come sviluppatore web basato su PHP, ti preoccupi di quante istruzioni CPU usa il tuo codice? Il più delle volte no, non proprio. Ma a volte è utile saperlo, per due motivi: può spiegare le decisioni prese dalle tue biblioteche; e a volte devi preoccuparti della velocità nel tuo codice.

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.