Pregunta

Tenga en cuenta la siguiente consulta:

SELECT * FROM Transactions
WHERE day(Stamp - interval 3 hour) = 1;

La Sello en la columna de los Transacciones Mesa es un TIMESTAMP y hay un índice en él. ¿Cómo podría cambiar esta consulta por lo que evita escaneos completos de tabla? (Es decir, usando Sello exterior de la día () función)

Gracias!

¿Fue útil?

Solución

Esta es la forma en que lo haría:

añadir algunos campos adicionales: año, mes, día o incluso hora, minuto, dependiendo del tráfico que se espera. A continuación, crear un disparador para rellenar los campos adicionales, tal vez de restar el intervalo de 3 horas de antelación. Finalmente construir algún índice en los campos extra.

Otros consejos

Si el objetivo es sólo para evitar escaneos completos de tabla y que tiene una clave primaria (PK decir el nombre) para transacciones, considerar la adición de cubrir índice

ALTER TABLE Transactions ADD INDEX cover_1 (PK, Stamp)

Entonces

SELECT * FROM Transactions WHERE PK IN (SELECT PK FROM Transactions
WHERE day(Stamp - interval 3 hour) = 1
 )

Esta consulta no debe utilizar los recorridos de tablas completos (sin embargo optimizador puede decidir utilizar análisis completo, si el número de filas de la tabla es pequeña o por cualquier otra razón estadística :))

Una mejor manera puede ser es el uso de la tabla temporal en lugar de subconsulta.

A menudo se puede reescribir la función para que tenga algo que parece WHERE Stamp=XXXX y XXXX es alguna expresión. Se puede crear una serie de entre las declaraciones de cada mes, WHERE Stamp BETWEEN timestamp('2010-01-01 00:00:00') AND timestamp ('2010-01-01 23:59:59') OR Stamp BETWEEN ..., pero no estoy seguro de que esto iba a utilizar el índice en este caso. Construiría una columna que era el día del mes como @petr sugiere.

Calcular el valor de sello deseada por separado antes de ejecutar la consulta principal, es decir.

Paso 1 - calcular el valor de indicación de deseada

Paso 2 - ejecutar una consulta donde Stamp> (valor calculado)

Debido a que no hay ningún cálculo en el paso 2, usted debe ser capaz de utilizar su índice.

Si he entendido bien, que básicamente quiere devolver todas las filas donde el sello cae en el primero de cada mes (sustraído el 3 horas)? Si (y esto es un gran si), que tiene una ventana fija de, por ejemplo los últimos 6 meses, sólo podría enumerar 6 pruebas de rangos. Pero el acceso sigue siendo, no estoy seguro indexado será más rápido de todos modos.

select *
  from transactions
 where stamp between timestamp '2010-06-01 03:00:00' and timestamp '2010-06-02 02:59:59'
    or stamp between timestamp '2010-07-01 03:00:00' and timestamp '2010-07-02 02:59:59'
    or stamp between timestamp '2010-08-01 03:00:00' and timestamp '2010-08-02 02:59:59'
    or stamp between timestamp '2010-09-01 03:00:00' and timestamp '2010-09-02 02:59:59'
    or stamp between timestamp '2010-10-01 03:00:00' and timestamp '2010-10-02 02:59:59'
    or stamp between timestamp '2010-11-01 03:00:00' and timestamp '2010-11-02 02:59:59'
    or stamp between timestamp '2010-12-01 03:00:00' and timestamp '2010-12-02 02:59:59';

NB! No estoy seguro de cómo el milisegundos parte de la marca de tiempo funciona. Es posible que necesite la almohadilla en consecuencia.

respuesta

El reprocesamiento de Petr un poco para evitar la cláusula IN, y para que sea para MyISAM o InnoDB.

Para MyISAM

ALTER TABLE Transactions ADD INDEX cover_1 (PK, Stamp)

O, para InnoDB, donde el PK está implícitamente incluido en cada índice,

ALTER TABLE Transactions ADD INDEX Stamp (Stamp)

Entonces

SELECT * 
FROM Transactions LEFT JOIN
  (
  SELECT PK 
  FROM Transactions 
  WHERE DAYOFMONTH(Stamp - interval 3 hour) = 1
  ) a ON Transactions.PK=a.PK

El sub consulta tendrá un índice sólo la ejecución, y la consulta externa sólo tirar de las filas de la tabla en la que llegó a través de a.PK.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top