2009-04-28 14 views
34

Tengo (por ejemplo) un índice:¿También selecciona un índice de varias columnas para una sola columna?

CREATE INDEX someIndex ON orders (customer, date); 

¿Este índice sólo acelerar consultas en las cliente y la fecha de se utilizan o se aceleran las consultas para una sola columna como esto también?

SELECT * FROM orders WHERE customer > 33; 

Estoy usando SQLite.


Si la respuesta es sí, ¿por qué es posible crear más de un índice por tabla?


Sin embargo, otra pregunta: ¿Cuánto más rápido es un índice combinado en comparación con los dos índices separat cuando usa ambas columnas en una consulta?

Respuesta

32

marc_s tiene la respuesta correcta a la primera pregunta. La primera clave en un índice de múltiples claves puede funcionar igual que un índice clave único, pero las claves posteriores no lo harán.

En cuanto a cuánto más rápido es el índice compuesto depende de sus datos y cómo se estructura el índice y la consulta, pero por lo general es significativo. Los índices esencialmente permiten a Sqlite hacer una búsqueda binaria en los campos.

Usando el ejemplo que dio si se ejecutó la consulta:

SELECT * from orders where customer > 33 && date > 99 

SQLite en primer lugar obtener todos los resultados utilizando una búsqueda binaria sobre toda la tabla, donde los clientes> 33. Entonces sería hacer una búsqueda binaria en un solo aquellos resultados que buscan fecha> 99.

Si hizo la misma consulta con dos índices separados en cliente y fecha, Sqlite tendría que realizar una búsqueda binaria en toda la tabla dos veces, primero para el cliente y nuevamente para la fecha.

Entonces, ¿cuánto de un aumento de velocidad verá depende de cómo se estructura el índice con respecto a su consulta. Idealmente, el primer campo en su índice y su consulta debería ser el que elimine la mayor cantidad de coincidencias posibles, ya que aumentará la velocidad al reducir en gran medida la cantidad de trabajo que debe realizar la segunda búsqueda.

Para obtener más información, consulte la siguiente: http://www.sqlite.org/optoverview.html

+2

SQLite NO usará la segunda columna de un índice si la primera columna fue una expresión de desigualdad (por ejemplo, cliente> 33). (la mayoría del motor de base de datos lo haría, difícil). – vmatyi

+1

Si crea dos índices separados, solo se usará uno de ellos, la otra expresión se evaluará en el conjunto de resultados generado por el primero. (en Oracle, podría ejecutar la búsqueda de dos índices e intersecar los conjuntos de resultados, si la optimización se basa en los costos y se cumplen ciertos criterios, pero ese es un caso raro). – vmatyi

5

Estoy bastante seguro de que esto funcionará, sí, lo hace en MS SQL Server de todos modos.

Sin embargo, este índice no le sirve de ayuda si necesita seleccionar solo la fecha, p. un rango de fechas En ese caso, es posible que deba crear un segundo índice justo en la fecha para que esas consultas sean más eficientes.

Marc

+0

Gracias, de eso no estaba seguro. Crearé dos índices separados en ese caso. –

3

que comúnmente se utilizan índices para ordenar a través de datos combinados Deseo paginate o solicitud "streamily".

Suponiendo que un cliente puede realizar más de un pedido ... y existen clientes de 0 a 11 y hay varios pedidos por cliente, todos insertados en orden aleatorio. Quiero ordenar una consulta basada en el número de cliente seguido de la fecha. También debe ordenar el último campo de id para dividir los conjuntos en los que un cliente tiene varias fechas idénticas (incluso si eso nunca ocurre).

sqlite> CREATE INDEX customer_asc_date_asc_index_asc ON orders 
      (customer ASC, date ASC, id ASC); 

Obtener página 1 de una consulta ordenada (limitado a 10 artículos):

sqlite> SELECT id, customer, date FROM orders 
      ORDER BY customer ASC, date ASC, id ASC LIMIT 10; 

2653|1|1303828585 
2520|1|1303828713 
2583|1|1303829785 
1828|1|1303830446 
1756|1|1303830540 
1761|1|1303831506 
2442|1|1303831705 
2523|1|1303833761 
2160|1|1303835195 
2645|1|1303837524 

obtener la página siguiente:

sqlite> SELECT id, customer, date FROM orders WHERE 
      (customer = 1 AND date = 1303837524 and id > 2645) OR 
      (customer = 1 AND date > 1303837524) OR 
      (customer > 1) 
      ORDER BY customer ASC, date ASC, id ASC LIMIT 10; 

2515|1|1303837914 
2370|1|1303839573 
1898|1|1303840317 
1546|1|1303842312 
1889|1|1303843243 
2439|1|1303843699 
2167|1|1303849376 
1544|1|1303850494 
2247|1|1303850869 
2108|1|1303853285 

Y así sucesivamente ...

Tener los índices en su lugar reduce el escaneo del índice del lado del servidor cuando de lo contrario utilizaría una consulta DESPLAZADA junto con un LÍMITE. El tiempo de consulta se hace más largo y las unidades buscan más, cuanto más alto va el desplazamiento. Usar este método elimina eso.

Se recomienda utilizar este método si planea unir datos posteriormente pero solo necesita un conjunto limitado de datos por solicitud. Únase a un SUBSELECTO como se describe arriba para reducir la sobrecarga de memoria para tablas grandes.

+0

Esto también ayuda a eliminar el tiempo de comando innecesario del lado del servidor ... si usaras ** datetime (date, 'unixepoch', 'localtime') ** en lugar de ** date ** como columna de retorno ... seguramente ser limitado Creo que sería de todos modos, depende del motor. – whardier

Cuestiones relacionadas