2010-10-25 19 views
12

Estructura de tabla:índice de fecha y hora de MySQL no está funcionando

+-------------+----------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+-------------+----------+------+-----+---------+----------------+ 
| id   | int(11) | NO | PRI | NULL | auto_increment | 
| total  | int(11) | YES |  | NULL |    | 
| thedatetime | datetime | YES | MUL | NULL |    | 
+-------------+----------+------+-----+---------+----------------+ 

filas en total:

mysql> explain select * from out where thedatetime <= NOW(); 
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+ 
| 1 | SIMPLE  | out   | ALL | thedatetime | NULL | NULL | NULL | 137967 | Using where | 
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+ 

La consulta real es mucho más larga con más uniones entre tablas, el punto es, que pueda Obtenga la tabla para usar el índice datetime. Esto va a ser difícil para mí si quiero seleccionar todos los datos hasta cierta fecha. Sin embargo, noté que puedo hacer que MySQL use el índice si selecciono un subconjunto más pequeño de datos.

mysql> explain select * from out where thedatetime <= '2008-01-01'; 
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+ 
| id | select_type | table  | type | possible_keys | key   | key_len | ref | rows | Extra  | 
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+ 
| 1 | SIMPLE  | out   | range | thedatetime | thedatetime | 9  | NULL | 15826 | Using where | 
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+ 

mysql> select count(*) from out where thedatetime <= '2008-01-01'; 
+----------+ 
| count(*) | 
+----------+ 
| 15990 | 
+----------+ 

Entonces, ¿qué puedo hacer para asegurarme de que MySQL usará el índice sin importar la fecha que puse?

+0

Como 'EXPLAIN' indica que el índice es 'usado', o más correctamente, * se considera * - en ambos casos. Mi respuesta a continuación explica en detalle. Por otro lado, si * estás * experimentando un mal rendimiento, entonces has simplificado demasiado la pregunta. – Unreason

Respuesta

7

Todo funciona como se supone que debe hacerlo. :)

Los índices están ahí para acelerar la recuperación. Lo hacen usando búsquedas de índice.

En primera consulta el índice no se utiliza debido a que va a recuperar todas las filas, y en este caso mediante el índice es más lento (lookup index, get row, lookup index, get row ... x número de filas es más lento que get all rows tabla == escanear)

En la segunda consulta está recuperando solo una parte de los datos y, en este caso, la exploración de la tabla es mucho más lenta.

El trabajo del optimizador es utilizar las estadísticas que RDBMS guarda en el índice para determinar el mejor plan. En el primer caso, el índice fue considerado, pero el planificador (correctamente) lo tiró.

EDITAR
Es posible que desee leer algo como this para obtener algunos conceptos y palabras clave en relación con planeador de consultas MySQL.

+0

Supongo que ese es el motivo (traté de aplicar esta respuesta a otras tablas). Necesito leer más acerca de los Índices de MySQL, así que gracias por el enlace. – amree

11

Hay dos cosas en juego aquí -

  1. índice no es lo suficientemente selectiva - si el índice abarca más de aprox. 30% de las filas, MySQL decidirá que una exploración de tabla completa es más eficiente. Al contratar el rango de las patadas del índice en.

  2. Un índice por tabla en una unión

La consulta real es mucho más larga con más uniones de tablas, el punto es ...

El punto es exactamente porque tiene uniones que probablemente no puede usar ese índice. MySQL puede usar un índice por tabla en una combinación (a menos que califique para una optimización index-merge). Si la clave primaria ya se usa para la unión, no se usará la hora de la fecha. Para usarlo, debe crear un índice de varias columnas en la clave de combinación + índice de fecha y hora, en el orden correcto.

Compruebe el EXPLAIN de la consulta real para ver qué clave utiliza MySQL para la unión. Modifique ese índice para incluir también la columna thedatetime, o cree un nuevo índice de varias columnas de ambos (dependiendo de para qué use la clave join).

+0

Gracias por la primera respuesta y la explicación, pero tengo que marcar Sinrazón ya que él/ella respondió primero. – amree

+0

Dio una buena explicación de por qué la búsqueda de índice es más lenta para un índice no selectivo –

Cuestiones relacionadas