Le Bool / Bit sono più veloci dei numeri interi

6

Come suggerisce il titolo, mi chiedo se bool o bit siano più veloci dell'utilizzo di interi (1 e 0)? In particolare, penso alla loro velocità nelle istruzioni CASE, ancor più specificamente in T-SQL (anche se sarebbe interessante ascoltare le esperienze di altre lingue).

Per alcuni contesti, ho un'istruzione SELECT piuttosto grande su una grande tabella che deve trasformare molti dati basati sul numero intero sia 1 o 0, e stava considerando la conversione degli interi in bit per un aumento delle prestazioni.

EDIT:

Grazie a tutti per le vostre risposte. Sembrava quasi che tu mi stessi dando quasi lo stesso consiglio in modo leggermente diverso o con diversi livelli di dettaglio.

    
posta CatchingMonkey 27.09.2011 - 11:18
fonte

8 risposte

13

Si potrebbe andare qui e fare speculazioni selvagge qui, o anche ipotesi formulate, ma la verità è che probabilmente non ha importanza, e se lo fa, dipenderà da molti altri fattori. L'unico modo per scoprirlo è il profilo e, quando lo fai, prima assicurati di escludere altri fattori (carico di sistema, frammentazione, ecc.).

La mia scommessa sarebbe che la differenza sarebbe trascurabile, e che c'è molto di più da vincere altrove - impostare indici sensibili, join di profili vs sottoquery, usare il caching laddove possibile, sperimentare molte piccole query contro poche grandi query, evitare inutili accessi al database, buffer dei risultati accumulati, ecc.

Il fatto è che l'ottimizzazione di interi e bool non ti darà mai più di un aumento di velocità lineare, e l'aumento non sarà grande - se ottieni il 5%, considera la tua fortuna. Quel 5% verrà distrutto se la tua query esegue un join esterno che richiede scansioni complete su entrambe le tabelle unite quando una tabella è molto grande e aggiungi una riga all'altra.

    
risposta data 27.09.2011 - 11:39
fonte
6

Non ti preoccupare.

Se sei particolarmente interessato a T-SQL, questo implica che stai usando un database. Molto probabilmente un database su disco.

L'accesso al disco è più lento di ordini di qualsiasi operazione della CPU o accesso alla memoria. Toccando il disco una sola volta, per leggere un singolo blocco di dati, è probabile che ci vorrà più del tempo totale impiegato per fare tutti i confronti che stai facendo.

Se riscontri problemi di prestazioni, profila il codice per scoprire dove si trova il vero problema piuttosto che concentrarti immediatamente su cose che molto probabilmente occupano meno dell'1% del tempo di esecuzione totale (e, quindi, può migliorare le prestazioni di meno di 1% anche se completamente rimosso). Molto probabilmente, otterrai il miglior ritorno sull'investimento di ottimizzazione migliorando i tuoi algoritmi piuttosto che cambiando i tipi di dati.

    
risposta data 27.09.2011 - 11:34
fonte
4

Solo per darti più di due parole e mezzo che ho scritto come commento, passiamo al livello del processore e cerchiamo di scoprire qual è la differenza in merito a questa domanda.

In primo luogo, un processore carica sempre una dimensione di registro completa dei dati ogni volta che qualcosa deve essere elaborato. Quindi il minor numero di dati caricati, quando lo si utilizza per un confronto binario o intero, sarebbe 32 o 64 bit. Assumiamo 32 per il momento.

Quindi, la differenza tra i due è questa:

mov ax,[address]
cmp ax,1
jne label

o

mov ax,[address]
and ax,10h
je label

Perdonami se il mio assemblatore non è nel posto giusto, sono passati circa 13 anni. Ma la risposta è ancora valida. La differenza tra questi due dovrebbe al momento la generazione del processore essere praticamente pari a zero.

Quindi, c'è il motore di RDBMS. Potrebbe tradurre la tua dichiarazione CASE in qualcosa come l'assemblatore sopra, ma è probabile che lo trasformi in base alle sue regole.

Quindi, c'è il Query Optimizer. Qualunque cosa faccia, può essere determinata, in genere da qualcosa come EXPLAIN (in MySQL), c'è una funzione simile in MS-SQL-Server che spiega il piano di esecuzione.

Quindi, per testare la velocità, hai bisogno di un ambiente che possa ignorare l'interferenza da processi, meccanismi di memorizzazione e simili.

Tutto ciò rende difficile testare queste cose e i risultati sono al massimo speculativi. Di solito il tempo speso a capire queste piccole differenze può essere usato per un uso molto più grande, ottimizzando gli indici o le strutture dati, i parametri del server o le istruzioni SELECT.

Saluti.

    
risposta data 27.09.2011 - 11:47
fonte
3

Le altre risposte hanno toccato il modo in cui il processore può gestire un int contro come gestirà un po '. Alcune altre cose da considerare:

Se nella tabella sono presenti più campi di questo tipo, memorizzarli come bit dovrebbe darti un vantaggio nella dimensione della riga ( da MSDN ):

The SQL Server Database Engine optimizes storage of bit columns. If there are 8 or less bit columns in a table, the columns are stored as 1 byte. If there are from 9 up to 16 bit columns, the columns are stored as 2 bytes, and so on.)

Quindi, nel migliore dei casi, per il "prezzo" di un int (4 byte), è possibile memorizzare il 32% di campi dibit. Non voglio generalizzare troppo, ma l'accesso al disco è spesso un collo di bottiglia; riducendo la quantità di dati che stai immagazzinando fisicamente porterai a query più veloci.

Le persone tendono anche a concentrarsi sul rendimento dei campi bit negli indici. Ho riscontrato alcuni casi in cui le persone hanno modificato i campi bit in char (1) per consentire l'indicizzazione del campo (soprattutto perché non è stato possibile indicizzare un campo bit prima di SQL 2005). La verità è che, indipendentemente dal modo in cui è memorizzato, se il tuo campo ha solo due valori possibili, avrai problemi a convincere SQL Server che valga la pena utilizzarlo come indice, a meno che non venga usato in combinazione con altri campi.

    
risposta data 27.09.2011 - 12:23
fonte
2

Se la tua attuale implementazione non riesce a soddisfare i requisiti di rendimento, usa un profiler per identificare dove il tempo è sprecato.

Se identificherai i bit e gli interi per essere un problema di prestazioni, allora correggilo.

    
risposta data 27.09.2011 - 11:31
fonte
1

L'uso dei bit ha senso invece degli interi quando si utilizzano indici di mappe di bit (non disponibili in SQL Server, ma possono essere trovati in Oracle) e quando si utilizzano i filtri di bitmap (disponibili in SQL Server). Dalla tua domanda, questo non è quello che stai cercando, ma penso che possa interessarti perché mostra un'applicazione pratica che usa binari su altri tipi di dati nella progettazione di database.

Il seguente link fornisce alcuni dettagli:

link

    
risposta data 27.09.2011 - 12:45
fonte
1

Questa risposta non è specifica per T-SQL o SQL, ma è una risposta più generale al titolo di questa domanda, "Are Bools / Bits Faster Than Integers", questo è certamente vero per alcuni microcontrollori che in realtà hanno un "bit" tipo di dati nell'hardware , come l'architettura 8051 e molti processori PIC di Microchip.

Nell'8051, la memoria bit indirizzabile nella RAM viene eseguita dagli indirizzi da 0x20 a 0x2f (128 bit in totale) e qualsiasi SFR (registro delle funzioni speciali) il cui indirizzo termina con 0 o 8 (un altro potenziale di 128 bit, ma non tutti sono implementati). Per supportare questi, l'8051 ha diverse istruzioni bit-indirizzabili come bit impostato, clear bit, complemento bit, jump se bit set o clear e molti altri. I bit RAM sono molto utili per l'uso come flag e i bit SFR consentono di impostare, alternare e cancellare individualmente i registri.

Nella maggior parte dei PIC (ma non in PIC32), tutte le porte interne RAM e I / O sono indirizzabili tramite bit e supportate da istruzioni quali set bit, clear bit e skip se un bit viene impostato o ripristinato. Dal momento che il registro di lavoro WREG e il registro di stato sono mappati anche agli indirizzi interni, si possono eseguire anche test di bit su quelli.

Sulle CPU che non hanno istruzioni bit-indirizzabili, come hanno notato altri poster, sarebbe necessario caricare un'intera parola dalla memoria e fare un'operazione bit-saggio su di essa, che potrebbe richiedere fino a tre istruzioni: carica, e / o / xor, e archivia o dirama.

I compilatori C per 8051 e PIC hanno in genere un tipo di dati "bit" oltre a char, short, int e long per consentire al codice C di sfruttare queste operazioni.

    
risposta data 28.09.2011 - 00:09
fonte
0

La risposta semplice: dipende.

La risposta più complessa: dipende da come la lingua, il compilatore e il runtime gestiscono bool o bit e la lunghezza della parola dei registri della CPU (64, 32, anche 16 o 8 hanno ancora un certo uso in dispositivi informatici più semplici ).

Ci sono un paio di modi per impostare un booleano:

  • Tipo di dati enumerati: public enum Bool {false, true}; . Questo è probabilmente il meno efficiente in termini di spazio, in quanto a seconda del linguaggio / compilatore un enum viene solitamente trasformato in un gruppo di costanti di byte, con il controllo del compilatore per garantire che non venga mai usato un valore non valido. Tuttavia, la maggior parte dei computer gestisce i valori di byte in modo molto efficiente; c'è bisogno di una matematica binaria molto piccola con loro.
  • Bitmask: quando viene utilizzato, è quasi sempre dietro le quinte, anche se .NET ha "Flag Enum" che consentono di impostare in modo specifico più bit su un valore composito. L'idea per bool è la stessa; il tuo compilatore prenderà ogni bool che ha lo stesso scope e li impacchetterà in byte. Il secondo booleano da dichiarare sarebbe il secondo bit da sinistra o da destra, e può essere testato con qualche semplice matematica binaria: a&0x02 >> 1 restituirà un 1 o 0 che rappresenta quel particolare booleano fuori dal byte.

Tutto ciò che so dice che ogni booleano ottiene un byte in tutte le applicazioni più critiche alla memoria, simile alla prima opzione, perché il calcolo extra per l'impacchettamento dei bit rallenta notevolmente l'applicazione per salvare un misero 8 byte di spazio di archiviazione e solo quando i booleani non sono attivamente necessari.

    
risposta data 27.09.2011 - 18:52
fonte

Leggi altre domande sui tag