¿Hay alguna ganancia de rendimiento al indexar un campo booleano?

103

Estoy a punto de escribir una consulta que incluye un WHERE isok=1. Como su nombre lo indica, isokes un campo booleano (en realidad, TINYINT(1) UNSIGNEDse establece en 0 o 1 según sea necesario).

¿Hay alguna mejora en el rendimiento al indexar este campo? ¿El motor (InnoDB en este caso) funcionaría mejor o peor buscando el índice?

Niet the Dark Absol
fuente
posible duplicado de los campos booleanos
Maxim Krizhanovsky

Respuestas:

80

Realmente no. Deberías pensar en ello como en un libro. Si solo hubiera 3 tipos de palabras en un libro y las indexara todas, tendría el mismo número de páginas de índice que las páginas normales.

Habría una ganancia de rendimiento si hay relativamente pocos registros de un valor. Por ejemplo, si tiene 1000 registros y 10 de ellos son VERDADEROS, sería útil buscar conisok = 1

Como mencionó Michael Durrant, también hace que la escritura sea más lenta.

EDITAR: Posible duplicación: Indexación de campos booleanos

Aquí explica que incluso si tiene un índice, si tiene demasiados registros, no usa el índice de todos modos. MySQL no usa índice al verificar = 1, pero lo usa con = 0

Michael Koper
fuente
4
Parece que "sí: 2 - no: 1". Alguien se equivoca aquí, pero ¿quién?
Niet the Dark Absol
4
Esto no es del todo correcto, sin un índice mySql necesita escanear toda la tabla para encontrar las filas relevantes.
ilanco
4
de lo contrario, escanearía todo el índice. (que es igual de largo en la mayoría de los casos)
Michael Koper
1
Puede marcar la diferencia. Simplemente reduzca el tiempo de ejecución a la mitad de una consulta simplemente agregando un índice, y las escrituras son raras y lo suficientemente baratas como para que realmente no nos importe la penalización. Como con todo, no asuma, mida (también porque las bases de datos no siempre se comportan como esperaría lógicamente)
Eelco
6
Esto supone una distribución equitativa entre VERDADERO y FALSO. Como lo menciona @oucil a continuación, si está buscando un valor booleano que es bastante raro, aún podría tomar un tiempo. No digo que siempre deba indexar, pero supongo que la naturaleza de sus datos y sus consultas también son importantes en la mayoría de los motores de bases de datos.
mahemoff
118

Solo para poner un punto más fino sobre varias otras respuestas aquí, ya que en mi experiencia, aquellos que miran preguntas como esta están en el mismo barco que nosotros, todos hemos escuchado que indexar campos booleanos no tiene sentido, y sin embargo ...

Tenemos una tabla con aproximadamente 4 millones de filas, solo alrededor de 1000 o más a la vez tendrán un interruptor booleano marcado y eso es lo que buscamos. Agregar un índice en nuestro campo booleano aceleró las consultas en órdenes de magnitud, pasó de aproximadamente 9+ segundos a una fracción de segundo.

oucil
fuente
Sí, aunque definitivamente debería tratar de comprender el 'por qué' de las cosas, siempre mida y pruebe diferentes cosas en su conjunto de datos real para ver si su teoría coincide con el comportamiento real del motor de base de datos (se sorprendería ... )
Eelco
8
@Eelco Tienes razón, pero en este caso, el resultado coincide con la teoría básica. La idea básica de que debería ser insignificante solo tiene sentido si hay un 50% de probabilidades de encontrar elementos que coincidan con su búsqueda. Luego, para encontrar 100 coincidencias, la base de datos necesita iterar 200 elementos. Pero si los elementos solo coinciden el 1% del tiempo, necesitaría iterar 10,000 elementos.
mahemoff
7
Me gusta cuando la gente realmente prueba cosas en el campo y da retroalimentación de rendimiento en lugar de simplemente filosofar.
Viktor Joras
WHERE my_col > 0 en lugar de my_col = 1también parece ayudar a la velocidad
Aaron
28

Depende de las consultas reales y de la selectividad de la combinación índice / consulta.

Caso A : condición WHERE isok = 1y nada más allí:

SELECT *
FROM tableX
WHERE isok = 1
  • Si el índice es lo suficientemente selectivo (digamos que tiene 1 millón de filas y solo 1k isok = 1), entonces el motor SQL probablemente usará el índice y será más rápido que sin él.

  • Si el índice no es lo suficientemente selectivo (digamos que tiene 1 millón de filas y más de 100 mil isok = 1), entonces el motor SQL probablemente no usará el índice y hará un escaneo de tabla.

Caso B : condición WHERE isok = 1y más cosas:

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

Entonces, depende de qué otros índices tenga. Un índice en another_columnprobablemente sería más selectivo que el índice en el isokque solo tiene dos valores posibles. Un índice en (another_column, isok)o (isok, another_column)sería incluso mejor.

ypercubeᵀᴹ
fuente
Creo que esta es la respuesta más correcta en comparación con la superior. también la distribución de los datos.
tyan
12

Depende de la distribución de los datos.

Imagine que tengo un libro con 1000 páginas escritas a máquina, y las únicas palabras en mi libro son "sí" y "no" repetidas una y otra vez y distribuidas al azar. Si me pidieran que encierre en un círculo todas las instancias de 'sí', ¿ayudaría un índice en la parte posterior del libro? Depende.

Si hubiera una distribución aleatoria mitad y mitad de sí y no, buscar en el índice no ayudaría. El índice haría que el libro fuera mucho más grande y, de todos modos, sería más rápido comenzar desde el frente y recorrer cada página buscando todas las instancias de 'sí' y rodeándolas, en lugar de buscar cada elemento en el índice y luego tomando la referencia de la entrada del índice a la página a la que se refiere.

Pero si hubiera, digamos, solo diez casos de 'sí' en mi libro de mil páginas y todo lo demás fueran solo millones de no, entonces un índice me ahorraría mucho tiempo para encontrar esos diez casos de 'sí' y rodearlos con un círculo. .

Lo mismo ocurre con las bases de datos. Si se trata de una distribución 50:50, entonces un índice no va a ayudar: el motor de la base de datos es mejor simplemente revisando los datos de principio a fin (escaneo completo de la tabla), y el índice simplemente agrandaría la base de datos, y más lento para escribir y actualizar. Pero si es algo así como una distribución de 4000: 1 (según oucil en este hilo), entonces una búsqueda de índice puede acelerarla enormemente, si es el 1 en 4000 elementos que está buscando.

Jinlye
fuente
5

No, normalmente no.

Por lo general, indexa los campos para la búsqueda cuando tienen una alta selectividad / cardinalidad. La cardinalidad de un campo booleano es muy baja en la mayoría de las tablas. También haría que sus escrituras fueran un poco más lentas.

Michael Durrant
fuente
3

En realidad, esto depende de las consultas que ejecute. Pero, en general, sí, además de indexar un campo de cualquier otro tipo.

Maksym Polshcha
fuente
2

Sí, un índice mejorará el rendimiento, verifique la salida de EXPLAIN con y sin el índice.

De los documentos:

Los índices se utilizan para buscar rápidamente filas con valores de columna específicos. Sin un índice, MySQL debe comenzar con la primera fila y luego leer toda la tabla para encontrar las filas relevantes. Cuanto más grande es la mesa, más cuesta. Si la tabla tiene un índice para las columnas en cuestión, MySQL puede determinar rápidamente la posición a buscar en el medio del archivo de datos sin tener que mirar todos los datos.

Creo que también es seguro decir que un índice no DISMINUIRÁ el rendimiento en este caso, por lo que solo tiene que beneficiarse de él.

ilanco
fuente
2
Un índice proporciona una gran cantidad de datos en el disco duro y hace que las escrituras sean más lentas, por lo que no solo se beneficia de ello.
Michael Koper
1
Es cierto, pero en este caso, una TINYINT(1) UNSIGNEDcolumna, el tamaño de los datos será pequeño.
ilanco
Y la sobrecarga de escritura agregada probablemente sea bastante baja
Eelco
¿No aumentará el tamaño del índice con la cantidad de filas a las que apunta, no solo con el tamaño del campo indexado?
Poolie