2010-02-27 13 views
74

Sono in procinto di creare un tavolo e mi sono chiesto.SQL SELECT speed int vs varchar

Se immagazzino, diciamo che le auto che hanno un marchio (fx BMW, Audi ect.), Faranno alcuna differenza sulla velocità di interrogazione se memorizzo la marca come int o varchar.

Così è

SELECT * FROM table WHERE make = 5 AND ...; 

Più veloce/più lento di

SELECT * FROM table WHERE make = 'audi' AND ...; 

o sarà la velocità più o meno la stessa cosa?

+1

Grazie per tutte le vostre risposte e ulteriori informazioni. Hai dimostrato il mio sospetto e reso facile la mia scelta. – googletorp

risposta

72

I confronti Int sono più veloci dei confronti varchar, per il semplice fatto che gli intro occupano molto meno spazio rispetto ai varchar.

Ciò vale sia per l'accesso non indicizzato che per quello indicizzato. Il modo più veloce per andare è una colonna int indicizzata.


Come vedo che hai codificato il postgreql domanda, potreste essere interessati a l'utilizzo dello spazio di diversi tipi di data:

+9

Ti riferisci a pg 7.4. Nelle versioni moderne, occupano 1 byte + lunghezza se si dispone di <126 byte.Si noti inoltre che il motivo per cui le stringhe sono molto più lente è spesso il fatto che il confronto sensibile alla collazione è estremamente costoso, non che la stringa richieda più spazio. Ma il risultato finale è lo stesso, ovviamente. –

+0

@Magnus - grazie per l'heads-up. Sentiti libero di modificare la mia risposta quando vedo che hai abbastanza punti Rep. –

+0

"non che la stringa richieda più spazio" ... le stringhe di caratteri sopra le dimensioni minime occupano molto più spazio dei numeri anche ad alta precisione, perché un numero (singolare) ha un'unità fissa, le stringhe sono sempre aggregate tipi. 8 byte per un numero a 64 bit 4 byte per carattere in una stringa, inclusi un byte di lunghezza o una struct; o un altro carattere di terminatore per implementazioni incredibilmente ingenue ... – MrMesees

1

Se si accende indicizzazione su uno dei campi, sarà più veloce. Per quanto riguarda la tua domanda, penso che int sia più veloce di varchar.

4

In generale, l'int sarà più veloce. Più lungo è il varchar più lento diventa

2

Suggerimento: Se i valori possibili per il campo fanno sarà mai (o raramente) il cambiamento, è possibile utilizzare ENUM come un compromesso. Combina una buona velocità con una buona leggibilità.

+1

Interessante, come sarà la differenza di velocità tra ENUM e int? – googletorp

+0

PostgresSQL ha un tipo di dati 'enum'? Pensavo fosse specifico per MySQL. –

+0

Postgres ha ENUM, ma non penso che sia implementato nello stesso modo di MySQL. http://www.postgresql.org/docs/current/static/datatype-enum.html – googletorp

15

Sarà un po 'più veloce utilizzando un int invece di un varchar. Più importante per la velocità è avere un indice sul campo che la query può utilizzare per trovare i record.

C'è un altro motivo per usare un int, e cioè per normalizzare il database. Invece di avere il testo "Mercedes-Benz" memorizzato migliaia di volte nella tabella, dovresti memorizzare il suo id e avere il nome del marchio memorizzato una volta in una tabella separata.

+0

Potresti spiegare di più? Intendi invece di 'Mercedes-Benz' per memorizzare migliaia di volte id' 1'. Ad esempio, tabella 'car_brands', colonne' Marche' e 'Id'. Riga 'Mercedes-Benz' e' 1'. E nella colonna della tabella principale 'Marche 'e valore' 1'. E quando 'SELEZIONA', quindi in un primo momento ottieni' Id' dalla tabella 'car_brands' e poi' SELEZIONA qualcosa FROM main_table WHERE Marche = (ID SELECT FROM car_brands DOVE Marche = Mercedes-Benz) '. O qualche altro approccio? – user2118559

+3

@ user2118559: Sì, è così che lo memorizzerai. Per ottenere i dati generalmente si usa un join piuttosto che un sottoquery: 'selezionare qualcosa da main_table c inner join car_brands b su b.Id = c.Brands dove b.Brands = 'Mercedes-Benz''. – Guffa

+0

Perché il downvote? Se non spieghi cosa pensi che sia sbagliato, non può migliorare la risposta. – Guffa

4

Indice o non, int è molto più veloce (più lungo è il varchar, più lento diventa).

Un'altra ragione: l'indice sul campo varchar sarà molto più grande di quello di int. Per tabelle più grandi può significare centinaia di megabyte (e migliaia di pagine). Ciò rende le prestazioni molto peggiori dal momento che la lettura dell'indice da sola richiede molte letture del disco.

+1

Ad esempio di 5 milioni di record di "audi", l'indice non contiene solo una copia della stringa di "audi" e 5 milioni di interi di primary_key? La differenza di dimensioni sarebbe davvero così grande, che sia vchar o intero? – lulalala

6

L'interruzione delle prestazioni effettive del confronto tra stringhe e non-float, in questo caso qualsiasi dimensione non firmata e firmata non ha importanza. La dimensione è in realtà la vera differenza di prestazioni. Be it 1byte + (fino a 126bytes) rispetto a 1,2,4 o 8 byte di confronto ...ovviamente non-float sono più piccoli di stringhe e float, e quindi più CPU friendly in assembly.

Confronto da stringa a stringa in tutte le lingue è più lento di qualcosa che può essere confrontato in 1 istruzione da parte della CPU. Anche il confronto di 8 byte (64 bit) su una CPU a 32 bit è ancora più veloce di un VARCHAR (2) o più grande. * Ancora una volta, guarda l'assemblaggio prodotto (anche a mano) ci vogliono più istruzioni per confrontare il char-by-char che il numero della CPU da 1 a 8 byte.

Ora, quanto più veloce? dipende anche dal volume dei dati. Se stai semplicemente confrontando 5 con 'audi' - e questo è tutto ciò che il tuo DB ha, la differenza risultante è così minima che non la vedresti mai. A seconda della CPU, dell'implementazione (client/server, web/script, ecc.) Probabilmente non lo vedrete fino a quando non raggiungerete qualche centinaio di confronti sul server DB (forse anche un paio di confronti di migliaia prima che sia evidente).

  • Per annullare la controversia non corretta sui confronti di hash. La maggior parte degli algoritmi di hashing sono lenti, quindi non trarrai vantaggio da cose come CRC64 e minori. Per oltre 12 anni ho sviluppato algoritmi di ricerca per motori di ricerca multi-contea e 7 anni per gli uffici di credito. Tutto ciò che è possibile mantenere numerico più velocemente ... ad esempio numeri di telefono, codici postali, valuta anche * 1000 (memorizzazione) div divisi di 1000 (recupero) è più veloce di DECIMAL per i confronti.

Ozz

0

Un po 'relativo. Sì, INT sarà più veloce, ma la domanda è se è evidente nella tua situazione. I VARCHAR sono solo parole piccole o testi più lunghi? e quante righe ci sono nella tabella? Se ci sono solo poche righe, molto probabilmente sarà interamente memorizzato in memoria (quando richiesto spesso), in tal caso non noterai molta differenza. Poi ovviamente c'è l'indicizzazione, che diventa più importante quando il tavolo cresce. L'uso di SSD potrebbe essere più veloce di HD con query ottimizzate. Anche i buoni controller del disco a volte velocizzano le query> 10 volte. Ciò potrebbe lasciare spazio per l'utilizzo di VARCHAR che semplifica la lettura e la scrittura delle query (non è necessario scrivere join complessi) e accelerare lo sviluppo. I puristi tuttavia non saranno d'accordo e normalizzeranno sempre tutto.

16

Alcuni punti di riferimento di massima:

4 milioni di record in Postgres 9.x

Table A = base table with some columns 
Table B = Table A + extra column id of type bigint with random numbers 
Table C = Table A + extra column id of type text with random 16-char ASCII strings 

Risultati su 8 GB di RAM, i7, SSD portatile:

Size on disk:    A=261MB  B=292MB  C=322MB 
Non-indexed by id: select count(*), select by id: 450ms same on all tables 
Insert* one row per TX:  B=9ms/record  C=9ms/record 
Bulk insert* in single TX: B=140usec/record C=180usec/record 
Indexed by id, select by id: B=about 200us  C=about 200us 

* inserts to the table already containing 4M records 

modo che appaia come per questo setup, purché gli indici si adattino alla RAM, bigint vs testo a 16 caratteri non fa differenza in termini di velocità.

+0

Molto interessante. Come mai la differenza è trascurabile? –