Cosa guadagnano 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 su Google non aumentano molto: perché i rigorosi tipi di dati?

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

Ma ciò che io non capisco è quale sia il vantaggio di avere tanti tipi di dati diversi:

  • Perché mediumtext , longtext e text ?
  • Perché decimal , float e int ?
  • ecc.

Qual è il vantaggio di dire al database "Ci saranno solo 256 byte di dati di 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?

    
posta john doe 26.05.2017 - 20:13
fonte

9 risposte

50

SQL è un linguaggio staticamente digitato. Ciò significa che devi sapere di che tipo è una variabile (o campo, in questo caso) prima che tu possa usarla. Questo è l'opposto delle lingue dinamicamente tipizzate, dove non è necessariamente il caso.

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

  • Gli indici , utilizzati per accedere rapidamente a record specifici, funzionano molto bene quando la dimensione è fissa. Considera 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) rispetto ai valori nell'indice e trovare i record desiderati più velocemente .

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

  • SQL è stato progettato negli anni '70. Nei primi tempi del microcomputing, 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 per esso? Quello è lo spazio sprecato nell'era della memoria limitata. Anche nei tempi moderni, quei byte sprecati in più possono sommare e uccidere le prestazioni della cache di una CPU. Ricorda che si tratta di motori di database che possono essere utilizzati per centinaia di transazioni al secondo, non solo per il tuo piccolo ambiente di sviluppo.

  • Lungo le linee di archiviazione limitata, è utile essere in grado di adattare un singolo record in una singola pagina in memoria. Una volta che vai su una pagina, ci sono più mancate pagine e più lento accesso alla memoria. I motori più recenti hanno ottimizzazioni per rendere questo meno un problema, ma è ancora lì. Misurando i dati in modo appropriato, è possibile attenuare questo rischio.

  • Moreso nei tempi moderni, SQL viene utilizzato per collegarsi ad altre lingue tramite ORM o < a href="https://en.wikipedia.org/wiki/Open_Database_Connectivity"> ODBC o qualche altro livello. Alcune di queste lingue hanno regole che richiedono tipi forti e statici. È meglio conformarsi ai requisiti più rigidi, poiché i linguaggi tipizzati dinamicamente possono gestire tipi statici più semplici rispetto al 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 sono non strongmente 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 ad es. un database Oracle aziendale che serve milioni di richieste al minuto.

    
risposta data 26.05.2017 - 20:48
fonte
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:

  • Limiti di business / design: che consentirebbero il numero 7626355112 nella colonna HEIGHT della tabella PERSON sarebbe errato. Consentire "Howya" nella colonna DATE di una FATTURA sarebbe sbagliato.
  • Meno codice soggetto a errori: non devi scrivere codice per assicurarti che i dati recuperati da una colonna di data siano realmente una data. Se i tipi di colonna fossero dinamici, dovresti eseguire molti controlli di tipo durante la lettura.
  • Efficienza informatica: se una colonna è di tipo INTEGER e tu SUM (), l'RDBMS non deve applicare aritmetica in virgola mobile.
  • Efficienza dello storage: affermando che una colonna è VARCHAR (10) consente all'RDBMS di allocare lo spazio in modo più preciso.
  • Integrità referenziale e unicità: PK (o FKs) di una tabella non dovrebbero consentire i float, poiché l'uguaglianza in virgola mobile è complicata, quindi devi dichiararli in un tipo non float, come caratteri o numeri interi.
  • Esistono RDBMS con tipi di colonna dinamici (non rigidi) (SQLite) . Usa il concetto di "tipo affinità" pur continuando a consentire di inserire virtualmente qualsiasi cosa in qualsiasi colonna senza lamentarsi. Ci sono trade-off che non verranno discussi qui. Vedi questa domanda .
risposta data 26.05.2017 - 20:41
fonte
8

È così che il codice sottostante in cui è scritto il database può allocare e utilizzare record a dimensione fissa, se sa che un campo specifico può contenere da 0 a 256 caratteri di testo, quindi può allocare un blocco di 256 byte per archiviare in.

Questo rende le cose molto più veloci, ad es. non devi allocare spazio di archiviazione aggiuntivo quando l'utente digita, poiché un determinato campo inizia sempre x byte nel record una ricerca o seleziona su quel campo sa di controllare sempre x byte in ogni record, ecc.

    
risposta data 26.05.2017 - 20:42
fonte
6

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

1) quando il motore del database sta attraversando le righe in una tabella non deve fare alcun stravagante parsing per determinare dove finisce ogni record, può solo sapere che ogni riga è composta, diciamo, da 32 byte, e quindi per ottenere il record successivo è sufficiente aggiungere 32 byte alla posizione attuale dei record.

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 una elaborazione di dati potenzialmente costosa.

    
risposta data 26.05.2017 - 20:40
fonte
3

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

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

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

  3. La storia. Gli RDBMS sono stati avviati quando i computer disponevano di pochi megabyte di RAM e lo spazio di archiviazione su terabyte era enormemente costoso. Salvare una dozzina di byte in ogni riga di un tavolo potrebbe salvare migliaia di dollari e ore di tempo in quelle circostanze.

  4. La maledizione della base clienti. Gli RDBMS oggi sono pacchetti software molto complessi e altamente ottimizzati e sono stati utilizzati da decenni per accumulare dati. Sono maturi Lavorano. Un arresto anomalo di RDBMS con conseguente perdita di dati su larga scala è di per sé raramente raro in questi giorni. Passare a qualcosa con un sistema di digitazione dati più flessibile non vale il costo o il rischio per la maggior parte delle organizzazioni.

Analogia: potrebbe essere ovvio che i sistemi metropolitani urbani funzionerebbero meglio (più silenzioso, più veloce, più efficiente dal punto di vista energetico) su una barra di guida più stretta. Ma come cambierai tutti i binari della metropolitana di New York per realizzare questi miglioramenti? Non lo sei, quindi ottimizzi quello che hai.

    
risposta data 28.05.2017 - 13:11
fonte
3

In generale, più dettagli comunichi al database su cosa stai memorizzando, più può provare a ottimizzare i vari parametri di rendimento relativi a quei dati, come la quantità di spazio da allocare disco o quanta memoria allocare quando lo si recupera.

Why mediumtext, longtext, and text?

Non sono sicuro di quale database usi quindi dovrò indovinare: Direi che due di questi tipi di dati hanno dei limiti superiori, uno di questi no. L'utilizzo di tipi di dati per il testo con limiti superiori indica al database la quantità di spazio di archiviazione necessaria per ogni record. È anche possibile che alcuni database possano avere diversi modi di archiviare un testo grande (eventualmente illimitato) rispetto a un testo di lunghezza fissa (questo può variare a seconda del database, controlla il tuo manuale per vedere i tuoi).

Why decimal, float, and int?

Diversi livelli di precisione richiedono diverse quantità di spazio di archiviazione, e non tutti gli usi richiedono i più alti gradi di precisione. Ad esempio, vedi qui: link

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

    
risposta data 26.05.2017 - 20:42
fonte
2

In una certa misura, è storico.

C'era una volta, i dati tabulari erano memorizzati in file composti da record a lunghezza fissa composti a loro volta da campi predefiniti in modo tale che un dato campo era sempre dello stesso tipo e nello stesso posto in ogni singolo record. Ciò ha reso l'elaborazione efficiente e limitata la complessità della codifica.

Aggiungi alcuni indici a tale file e hai l'inizio di un database relazionale.

Man mano che i database relazionali si evolvevano, iniziarono a introdurre più tipi di dati e opzioni di archiviazione, inclusi campi di testo a lunghezza variabile o binari. Tuttavia, questo ha introdotto record a lunghezza variabile e ha rotto la capacità di localizzare in modo coerente i record tramite calcoli o campi tramite un offset fisso. Non importa, le macchine sono molto più potenti oggi di quanto non fossero allora.

A volte è utile impostare una dimensione specifica per un campo per rinforzare un po 'di logica aziendale, ad esempio 10 cifre per un numero di telefono nordamericano. Per la maggior parte del tempo è solo un po 'di retaggio informatico.

    
risposta data 28.05.2017 - 03:43
fonte
1

Se un database utilizza record di dimensioni fisse, qualsiasi record nel database continuerà a stare nella stessa posizione, anche se i suoi contenuti sono modificati. Al contrario, se un database tenta di archiviare i record utilizzando esattamente la quantità di memoria necessaria per i loro campi, il cambiamento del nome di Emma Smith in Emma Johnson potrebbe rendere il suo record troppo grande per adattarsi alla sua posizione attuale. Se il record viene spostato in un posto con spazio sufficiente, qualsiasi indice che tenga traccia di dove sarà 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, quella lista sarà l'unica cosa che dovrebbe essere aggiornata se si sposta un record. Sfortunatamente, tali approcci hanno ancora costi significativi (ad esempio, mantenere una mappatura tra i numeri dei record e le posizioni richiederebbe che il recupero dei record richiederebbe un passaggio aggiuntivo per recuperare i dati associati a un dato numero di record). L'utilizzo di record di dimensioni fisse può sembrare inefficiente, ma rende le cose molto più semplici.

    
risposta data 26.05.2017 - 23:49
fonte
1

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

What is the benefit of telling the database "There'll only be 256 bytes of plain text data in entries to this column." or "This column can have text entries of up to 16,777,215 bytes"?

Come sospetti, il motivo ha a che fare con l'efficienza. Le perdite di astrazione . Una query come SELECT author FROM books può essere eseguita abbastanza rapidamente quando la dimensione di tutti i campi in la tabella è nota.

Come dice Joel,

How does a relational database implement SELECT author FROM books? In a relational database, every row in a table (e.g. the books table) is exactly the same length in bytes, and every fields is always at a fixed offset from the beginning of the row. So, for example, if each record in the books table is 100 bytes long, and the author field is at offset 23, then there are authors stored at byte 23, 123, 223, 323, etc. What is the code to move to the next record in the result of this query? Basically, it’s this:

pointer += 100;

One CPU instruction. Faaaaaaaaaast.

La maggior parte delle volte, lavori abbastanza lontano dalle puntigliose fondamenta a cui non devi preoccupartene. Come sviluppatore web basato su PHP, ti cura di quante istruzioni della CPU utilizza il tuo codice? Il più delle volte, no, non proprio. Ma a volte è utile sapere, per due ragioni: può spiegare le decisioni prese dalle tue biblioteche; e a volte devi preoccuparti della velocità nel tuo codice.

    
risposta data 27.05.2017 - 14:25
fonte

Leggi altre domande sui tag