C'è qualche miglioramento delle prestazioni nell'indicizzazione di un campo booleano?


103

Sto per scrivere una query che includa un file WHERE isok=1. Come suggerisce il nome, isokè un campo booleano (in realtà un TINYINT(1) UNSIGNEDche è impostato su 0 o 1 secondo necessità).

C'è qualche miglioramento delle prestazioni nell'indicizzazione di questo campo? Il motore (InnoDB in questo caso) funzionerebbe meglio o peggio cercando l'indice?


possibile duplicato dei campi booleani
Maxim Krizhanovsky

Risposte:


80

Non proprio. Dovresti pensarci come un libro. Se in un libro ci fossero solo 3 tipi di parole e le indicizzi tutte, avresti lo stesso numero di pagine indice delle pagine normali.

Ci sarebbe un miglioramento delle prestazioni se ci fossero relativamente pochi record di un valore. Ad esempio, se hai 1000 record e 10 di essi sono VERO, sarebbe utile se stai cercando conisok = 1

Come ha detto Michael Durrant, rende anche la scrittura più lenta.

EDIT: Possibile duplicazione: indicizzazione dei campi booleani

Qui spiega che anche se hai un indice, se hai troppi record non usa comunque l'indice. MySQL non usa index quando controlla = 1, ma lo usa con = 0


4
Sembra "sì: 2 - no: 1". Qualcuno ha torto qui, ma chi?
Niet the Dark Absol

4
Questo non è del tutto corretto, senza un indice mySql deve scansionare l'intera tabella per trovare le righe pertinenti.
ilanco

4
altrimenti scansionerebbe l'intero indice. (che è altrettanto lungo nella maggior parte dei casi)
Michael Koper

1
Può fare la differenza. Basta tagliare il tempo di esecuzione a metà di una query semplicemente aggiungendo un indice e le scritture sono abbastanza rare ed economiche da non preoccuparci davvero della penalità. Come con tutto, non dare per scontato, misurare (anche perché i database non si comportano sempre come ci si aspetterebbe logicamente)
Eelco

6
Ciò presuppone una distribuzione uguale tra VERO e FALSO. Come menzionato da @oucil di seguito, se stai cercando un valore booleano che è abbastanza raro, potrebbe comunque volerci un po '. Non sto dicendo che dovresti sempre indicizzare, ma presumo che la natura dei tuoi dati e le tue query siano importanti anche nella maggior parte dei motori di database.
mahemoff

118

Solo per mettere un punto più preciso su molte altre risposte qui, poiché nella mia esperienza, quelli che guardano domande come questa sono nella stessa barca che eravamo noi, abbiamo tutti sentito che l'indicizzazione dei campi booleani è inutile, eppure ...

Abbiamo una tabella con circa 4 milioni di righe, solo circa 1000 alla volta avrà un'opzione booleana contrassegnata ed è quello che cerchiamo. L'aggiunta di un indice sul nostro campo booleano ha velocizzato le query per ordini di grandezza, è passato da circa 9+ secondi a una frazione di secondo.


Sì, mentre dovresti assolutamente cercare di capire il `` perché '' delle cose, misura sempre insieme e prova cose diverse sul tuo set di dati effettivo per vedere se la tua teoria corrisponde al comportamento effettivo del motore db (rimarrai sorpreso ... )
Eelco

8
@Eelco Hai ragione, ma in questo caso, il risultato in realtà corrisponde bene alla teoria di base. L'idea di base che dovrebbe essere trascurabile ha senso solo se hai circa il 50% di probabilità di imbattersi in elementi che corrispondono alla tua ricerca. Quindi, per trovare 100 corrispondenze, il database deve iterare 200 elementi. Ma se gli elementi corrispondono solo l'1% delle volte, è necessario iterare 10.000 elementi.
mahemoff

7
Mi piace quando le persone provano effettivamente le cose sul campo e danno feedback sull'aumento delle prestazioni invece di filosofare.
Viktor Joras

WHERE my_col > 0 invece di my_col = 1sembra anche aiutare la velocità
Aaron

28

Dipende dalle query effettive e dalla selettività della combinazione indice / query.

Caso A : condizione WHERE isok = 1e nient'altro lì:

SELECT *
FROM tableX
WHERE isok = 1
  • Se l'indice è abbastanza selettivo (supponiamo di avere 1 milione di righe e solo 1k isok = 1), il motore SQL probabilmente utilizzerà l'indice e sarà più veloce che senza di esso.

  • Se l'indice non è sufficientemente selettivo (supponiamo di avere 1 milione di righe e più di 100k isok = 1), il motore SQL probabilmente non utilizzerà l'indice ed eseguirà una scansione della tabella.

Caso B : condizioni WHERE isok = 1e altro:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

Quindi, dipende da quali altri indici hai. Un indice su another_columnsarebbe probabilmente più selettivo dell'indice su isokcui ha solo due possibili valori. Un indice su (another_column, isok)o (isok, another_column)sarebbe anche meglio.


Penso che questa sia la risposta più corretta rispetto a quella in alto. anche la distribuzione dei dati.
tyan

12

Dipende dalla distribuzione dei dati.

Immagina di avere un libro con 1000 pagine dattiloscritte e le uniche parole nel mio libro erano "sì" e "no" ripetute più e più volte e distribuite casualmente. Se mi chiedessero di cerchiare tutte le istanze di "sì", sarebbe utile un indice in fondo al libro? Dipende.

Se ci fosse una distribuzione casuale metà e metà di sì e no, cercare nell'indice non sarebbe di aiuto. L'indice renderebbe il libro molto più grande, e comunque sarei più veloce ad iniziare dal davanti e lavorare su ogni pagina cercando tutte le istanze di "sì" e cerchiandole, piuttosto che cercare ogni elemento in l'indice e quindi prendendo il riferimento dalla voce di indice alla pagina a cui si riferisce.

Ma se ci fossero, diciamo, solo dieci istanze di "sì" nel mio libro di mille pagine e tutto il resto fossero solo milioni di no, allora un indice mi farebbe risparmiare un sacco di tempo nel trovare quei dieci casi di "sì" e circondarli .

È lo stesso nei database. Se è una distribuzione 50:50, un indice non aiuterà: il motore del database è meglio che analizzi i dati dall'inizio alla fine (scansione completa della tabella) e l'indice renderebbe il database più grande e più lento da scrivere e aggiornare. Ma se è qualcosa come una distribuzione 4000: 1 (come per oucil in questo thread), allora una ricerca di indice può velocizzarla enormemente, se è l'1 su 4000 elementi che stai cercando.


5

No, di solito no.

Di solito indicizzi i campi per la ricerca quando hanno un'elevata selettività / cardinalità. La cardinalità di un campo booleano è molto bassa nella maggior parte delle tabelle. Renderebbe anche le tue scritture leggermente più lente.


3

In realtà questo dipende dalle query che esegui. Ma, generalmente sì, oltre a indicizzare un campo di qualsiasi altro tipo.


2

Sì, un indice migliorerà le prestazioni, controlla l'output di EXPLAIN con e senza l'indice.

Dai documenti:

Gli indici vengono utilizzati per trovare rapidamente righe con valori di colonna specifici. Senza un indice, MySQL deve iniziare con la prima riga e quindi leggere l'intera tabella per trovare le righe pertinenti. Più grande è il tavolo, più questo costa. Se la tabella ha un indice per le colonne in questione, MySQL può determinare rapidamente la posizione in cui cercare nel mezzo del file di dati senza dover guardare tutti i dati.

Penso che sia anche sicuro dire che un indice non DIMINUISCE le prestazioni in questo caso, quindi devi solo guadagnare da esso.


2
Un indice fornisce molti dati sul disco rigido e rende la scrittura più lenta in modo da non trarne vantaggio.
Michael Koper

1
Vero, ma in questo caso, una TINYINT(1) UNSIGNEDcolonna, la dimensione dei dati sarà piccola.
ilanco

E il sovraccarico di scrittura aggiunto probabilmente piuttosto basso
Eelco

La dimensione dell'indice non crescerà con il numero di righe a cui punta, non solo con la dimensione del campo indicizzato?
poolie
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.