2009-07-07 24 views
9

Supongamos que tengo una tabla de base de datos con las columnas a, b y c. Planeo hacer consultas en las tres columnas, pero no estoy seguro de qué columnas en particular estoy consultando. Hay suficientes filas de la tabla que un índice acelera enormemente la búsqueda, pero se siente mal para que todas las permutaciones de posibles índices (como éste):¿Hay una manera mejor de indexar columnas múltiples que crear un índice para cada permutación?

a 
b 
c 
a, b 
a, c 
b, c 
a, b, c 

¿Hay una mejor manera de manejar este problema? (Es muy posible que indexe solo a, b, c solo, ya que esto reducirá el número de filas rápidamente, pero me pregunto si hay una mejor manera).

Si necesita ejemplos más concretos, en los datos de la vida real, las columnas son ciudad, estado y código postal. Además, estoy usando una base de datos MySQL.

Respuesta

19

En MS SQL el índice "a, b, c" lo cubrirá para los escenarios "a"; "a, b"; y "a, b, c". Por lo que sólo necesitaría los siguientes índices:

a, b, c 
b, c 
c 

No estoy seguro si MySQL funciona de la misma manera, pero yo asumiría así.

+7

Esta es la respuesta correcta. MySQL funciona de la misma manera, y esta técnica se llama "Prefijo de la izquierda". Del manual de MySQL en http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html: "Si la tabla tiene un índice de varias columnas, cualquier prefijo situado más a la izquierda del índice puede ser utilizado por el optimizador para buscar filas. Por ejemplo, si tiene un índice de tres columnas en (col1, col2, col3), tiene capacidades de búsqueda indexadas en (col1), (col1, col2) y (col1, col2, col3) . " – zombat

+0

Hmm, debería haber sabido esto. ;) Muy impresionante, voy a dar una oportunidad. –

+1

Es posible que también necesite a, c, pero depende de cómo se vean sus consultas.También puede necesitar el índice individual para cubrir el escenario O mencionado por Andriyev, no estoy seguro. –

1

Cuantos más índices cree, más se golpeará su rendimiento durante las operaciones de actualización y eliminación. Porque el índice mismo podría actualizarse.

Sí, puede usar índices de varias columnas. Algo así como

CREATE TABLE temp (
    id   INT NOT NULL, 
    a   INT NULL, 
    b   INT NULL, 
    c   INT NULL, 
    PRIMARY KEY (id), 
    INDEX ind1 (a,b,c), 
    INDEX ind2 (a,b) 
); 

Este tipo de índice, es decir IND1 seguramente le ayudará en las consultas como

SELECT * FROM temp WHERE a=2 AND b=3 AND c=4; 

Del mismo modo, ind2 le ayudará en consultas como

SELECT * FROM temp WHERE a=2 AND b=3; 

Pero estos índices ganado' t se utilizará si la consulta es algo así como

SELECT * FROM temp WHERE a=2 OR b=3 OR c=4; 

Aquí necesitará índices separados en a, b, y c.

Entonces, en lugar de tener tantos índices, estoy de acuerdo con lo que dijo John, es decir, tiene índices en a, b, c y si considera que su carga de trabajo cubre más consultas de varias columnas, puede cambiar a índices de varias columnas .

aplausos

+0

Esta tabla rara vez se actualiza, por lo que no me preocupa si la actualización es lenta. –

1

Dado que sus columnas son en realidad la ciudad, estado y código postal, sugeriría simplemente los siguientes índices:

índice (ZipCode)

Si estoy en lo correcto, Código Postal Los códigos no están duplicados en todos los Estados Unidos, por lo que no tiene sentido agregar información de la Ciudad o del Estado al índice porque tendrán el mismo valor para todos los Códigos Postales. Por ejemplo, 90210 siempre es Los Angeles, CA.

ÍNDICE (Ciudad (5)) o ÍNDICE (Ciudad (5)), Estado)

Esto es sólo un índice en las cinco primeras letras del nombre de la ciudad.En muchos casos, esto será lo suficientemente específico como para tener indexado el State no proporcionaría ningún filtro útil. Por ejemplo, 'Los A' seguramente serán discos de Los Angeles, CA. Tal vez haya otra ciudad pequeña en los EE. UU. Empezando por 'Los A', pero habrá tan pocos registros que no valga la pena saturar el índice con datos del Estado también. Por otro lado, algunos nombres de ciudades aparecen en muchos estados (me viene a la mente Springfield), por lo que en esos casos es mejor tener el Estado indexado también. Tendrá que averiguar qué índice es el más adecuado para su conjunto de datos. En caso de duda, iría con el segundo índice (Ciudad y Estado).

ÍNDICE (Estado, sort_field)

Estado es un índice bastante amplia (posiblemente NY y CA solo tendrá el 30% de los registros). Si planea mostrar esta información al usuario, por ejemplo, 30 registros a la vez, entonces tendrían una consulta que termina en

... WHERE STATE = "NY" 
ORDER BY <sort_field> 
LIMIT <number>, 30 

Para hacer que consulta eficiente, es necesario incluir la columna de clasificación en el Índice estatal Entonces, si muestra las páginas ordenadas por Apellido (suponiendo que tenga esa columna), entonces usaría ÍNDICE (Estado, Apellido (3)), de lo contrario MySQL tiene que ordenar todos de los registros 'NY' antes puede darte los 30 que quieres.

+2

Su información en códigos postales no es estrictamente correcta. Muchos códigos postales tienen más de un "nombre de lugar aceptable". Por ejemplo, "Hollywood, CA" es un nombre de lugar aceptable para 90028, a pesar de que Hollywood es solo un distrito de Los Ángeles y no una ciudad real. El "nombre de lugar predeterminado" para 90028 es en realidad "Los Angeles, CA". Además, a veces dos ciudades o porciones de dos ciudades estarán dentro del mismo código postal. Es cierto que cada código postal tiene exactamente un "nombre de lugar predeterminado", pero no puede confiar en eso para los datos ingresados ​​por el usuario. – Geerad

+0

Mientras haya (en la mayoría de los casos) no más de dos o tres nombres de lugares para cada código postal, el índice seguirá estando bien. –

+0

No estoy seguro de cuáles son los porcentajes, pero mi código postal tiene cuatro nombres permitidos. Y sé de otro que también tiene cuatro. –

1

Depende de su consulta sql.

índice (a, b, c) es diferente a índice (b, c, a) o índice (a, c, b)

4

utilizar índices para todas las posibles condiciones de igualdad N en columnas, necesitará C([N/2], N) índices, es decir N!/([N/2]! * (N - [N/2])!)

Lee este artículo en mi blog para explicaciones detalladas:

También puede leer la estricta matemática proof por el matemático ruso Egor Timoshenko (actualización: ahora en Inglés).

se puede, no obstante, obtener un rendimiento decente con menos índices empleando las siguientes técnicas:

Índice de fusión

Si las columnas col1, col2 y col3 son selectivos, entonces esta consulta

SELECT * 
FROM mytable 
WHERE col1 = :value1 
     AND col2 = :value2 
     AND col3 = :value3 

puede usar tres índices separados en col1, col2 y col3, seleccionar los ROWID 's que coinciden con cada condición por separado y a encontrar su intersección, como en:

SELECT * 
FROM (
     SELECT rowid 
     FROM mytable 
     WHERE col1 = :value1 
     INTERSECT 
     SELECT rowid 
     FROM mytable 
     WHERE col2 = :value2 
     INTERSECT 
     SELECT rowid 
     FROM mytable 
     WHERE col3 = :value3 
     ) mo 
JOIN mytable mi 
ON  mi.rowid = mo.rowid 

mapa de bits de indexación

PostgreSQL puede construir índices de mapa de bits en la memoria temporal derecha durante la consulta.

Un índice de mapa de bits es una matriz de bits contigua bastante compacta.

Cada bit configurado para la matriz indica que la correspondencia tid se debe seleccionar de la tabla.

Tal índice puede tomar pero 128M de almacenamiento temporal para una tabla con 1G filas.

La siguiente consulta:

SELECT * 
FROM mytable 
WHERE col1 = :value1 
     AND col2 = :value2 
     AND col3 = :value3 

primero asignar un mapa de bits rellenado con ceros lo suficientemente grande como para cubrir todas las posibles tid 's en la tabla (que es lo suficientemente grande como para tomar todas las tid' s de (0, 0) a la último tid, no tomando tid's faltantes en cuenta).

A continuación, buscará el primer índice, estableciendo los bits en 1 si cumplen la primera condición.

Luego escaneará el segundo índice, AND 'los bits que satisfacen la segunda condición con un 1. Esto dejará 1 solo para aquellos bits que satisfagan ambas condiciones.

Lo mismo para el tercer índice.

Finalmente, solo seleccionará las filas con el tid correspondiente al conjunto de bits.

El tid se buscará secuencialmente, por lo que es muy eficiente.

Cuestiones relacionadas