2012-01-31 13 views
33

Tengo una consulta de la siguiente forma:crear un índice en una marca de tiempo para optimizar la consulta

SELECT * FROM MyTable WHERE Timestamp > [SomeTime] AND Timestamp < [SomeOtherTime] 

me gustaría para optimizar esta consulta, y estoy pensando en poner un índice en marca de tiempo, pero no soy seguro si esto ayudaría Idealmente, me gustaría hacer que la marca de tiempo sea un índice agrupado, pero MySQL no admite índices agrupados, a excepción de las claves primarias.

  • MyTable tiene 4 millones de filas.
  • Timestamp es actualmente del tipo INT.
  • Una vez que se ha insertado una fila, nunca se cambia.
  • El número de filas con cualquier dado Timestamp es en promedio alrededor de 20, pero podría ser tan alto como 200.
  • filas recién insertadas tienen una Timestamp que es mayor que la mayoría de las filas existentes, pero podría ser menor que algunos de las filas más recientes.

¿Necesitaría un índice en Timestamp para optimizar esta consulta?

+1

Incluso en MSSQL si crea un índice agrupado en una columna no única, lo hace único bajo las carátulas. Seguramente, un índice ayudará a seleccionar pero ralentizar la inserción y el índice tomará espacio en el disco. Pero eso suena como un oficio que estás dispuesto a tomar. Pon el índice sobre la mesa y prueba. Los índices se usan para> y <. – Paparazzi

+0

¿Tiene un índice agrupado en esta tabla? –

+0

@BalamBalam Actualmente estoy diseñando una base de datos para consultas del tipo anterior, así que no puedo probar el rendimiento. – DanielGibbs

Respuesta

36

No hay dudas al respecto. Sin el índice, su consulta tiene que ver cada fila en la tabla. Con el índice, la consulta será más o menos instantánea en lo que respecta a la ubicación de las filas correctas. El precio que pagará es leve disminución en el rendimiento de las inserciones; pero eso realmente será leve.

+7

Por lo tanto, no hay inconveniente en el hecho de que el número de marcas de tiempo únicas es bastante alto y, por lo tanto, dará como resultado un índice bastante grande. – DanielGibbs

+1

Será instantáneo si la diferencia entre '[SomeOtherTime]' y '[SomeTime]' es pequeña. –

+1

Gracias @ypercube - solo califiqué eso en la respuesta :) - Yo diría que la desventaja de unos pocos megabytes de índice lo vale. ¡Las bases de datos son buenas para ese tipo de cosas! –

7

Definitivamente, debe usar un índice. MySQL no tiene idea en qué orden están esas marcas de tiempo, y para encontrar un registro para una marca de tiempo determinada (o rango de marca de tiempo) necesita buscar en cada registro. Y con 4 millones de ellos, ¡es bastante tiempo! Los índices son su manera de decirle a MySQL sobre sus datos: "Voy a ver este campo con bastante frecuencia, así que mantenga una lista de dónde puedo encontrar los registros para cada valor".

Los índices en general son una buena idea para los campos que consultan regularmente. La única desventaja de la definición de índices es que usan espacio de almacenamiento adicional, por lo tanto, a menos que tenga poco espacio, debería intentar usarlos. Si no se aplican, MySQL simplemente los ignorará de todos modos.

4

Si sus consultas son principalmente utilizando esta marca de tiempo, usted podría probar este diseño (ampliación de la clave principal con la marca de tiempo como primera parte):

CREATE TABLE perf (
    , ts INT NOT NULL 
    , oldPK 
    , ... other columns 
, PRIMARY KEY(ts, oldPK) 
, UNIQUE (oldPK) 
) ENGINE=InnoDB ; 

Esto asegurará que las consultas como la que usted envió voluntad utilizar la clave agrupada (primaria).

La desventaja es que sus insertos serán un poco más lentos. Además, si tiene otros índices en la tabla, usarán un poco más de espacio (ya que incluirán la clave primaria más amplia de 4 bytes).

La mayor ventaja de dicho índice agrupado es que las consultas con escaneos de rango grande, p. Ej. las consultas que tienen que leer grandes partes de la tabla o la tabla completa encontrarán las filas relacionadas secuencialmente y en la orden deseada (BY timestamp), que también será útil si desea agrupar por día, semana, mes o año.

El antiguo PK se puede seguir utilizando para identificar filas al mantener una restricción UNIQUE en él.


También es posible que desee echar un vistazo a TokuDB, una variante de MySQL (y de código abierto) que permite multiple clustered indices.

+0

La gran desventaja de este enfoque es que ahora necesita saber la marca de tiempo junto con la antigua PK para encontrar una fila por PK. –

+0

@DavidHarkness No, si el antiguo PK sigue siendo único. Editaré la respuesta para dejarlo en claro. –

+0

Sí, con la nueva restricción única eres bueno. Si la agrupación por fecha y hora es importante, el costo puede valer la pena. Tendré que considerar esto para dos tablas en el sistema que estoy construyendo, que son esencialmente registros de transacciones para informes. –

4

No estoy en desacuerdo con la importancia de indexar para mejorar los tiempos de consulta seleccionados, pero si puede indexar en otras claves (y forma sus consultas con estos índices), la necesidad de indexar en timestamp puede no ser necesaria.

Por ejemplo, si usted tiene una mesa con timestamp, category y userId, puede ser mejor para crear un índice en userId lugar. En una tabla con muchos usuarios diferentes, esto reducirá considerablemente el conjunto restante en el que buscar la marca de tiempo.

... y si no me equivoco, la ventaja de esto sería evitar la sobrecarga de crear el índice de marca de tiempo en cada inserción - en una tabla con altas tasas de inserción y marcas de tiempo altamente únicas esto podría ser una Importante consideración.

Estoy luchando con los mismos problemas de indexación basados ​​en marcas de tiempo y otras claves. Aún tengo que hacer pruebas para poder poner pruebas detrás de lo que digo aquí. Intentaré la devolución de datos en función de mis resultados.

Un escenario para una mejor explicación:

  1. marca de tiempo del 99% único
  2. ID de usuario 80% único
  3. categoría de 25% único

    • Indexación de marca de tiempo que reducirá rápidamente resultados de la consulta a 1% del tamaño de la tabla
    • La indexación en userId reducirá rápidamente los resultados de la consulta a 2 0% del tamaño de la tabla
    • Index Server en la categoría reducirá rápidamente resultados de la consulta a un 75% del tamaño de la tabla
    • inserción con índices de marca de tiempo tendrá lo alto **
    • A pesar de nuestro conocimiento de que nuestras inserciones respetarán el hecho de tienen marcas de tiempo incrementales, no veo ninguna discusión sobre la optimización de MySQL basada en claves incrementales.
    • La inserción con índices en userId tendrá una sobrecarga razonablemente alta.
    • La inserción con índices en la categoría tendrá una sobrecarga razonablemente baja.

** Lo siento, no sé la calculada por encima o inserción con la indexación.

Cuestiones relacionadas