2013-02-22 7 views
7

Ho questa tabella:MySQL Query dont't utilizza l'indice quando ci sono le variabili in DOVE

CREATE TABLE `ClientesHora_copy` (
`dia` varchar(6) default NULL, 
`hora` varchar(2) default NULL, 
`sit` varchar(17) default NULL, 
`nodo` varchar(6) default NULL, 
`clientes` decimal(41,0) default NULL, 
`segundos` double default NULL, 
`llamadas` decimal(41,0) default NULL, 
`fecha` datetime default NULL, 
KEY `nodo_fecha` (`nodo`,`fecha`), 
KEY `nodo` (`nodo`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

e questa query:

SET @sitio= 'ABA000'; 
SET @horaini='2013-02-12 15:18:00'; 
SET @horafin='2013-02-12 20:36:00';  
    EXPLAIN SELECT nodo,sit,clientes,segundos,llamadas,fecha,hora,@horaini AS horaini,@horafin AS horafin 
     FROM `ClientesHora_copy` 
     WHERE 
     nodo [email protected] 
     AND 
     fecha BETWEEN DATE_SUB(DATE_FORMAT(@horaini, "%Y-%m-%d %H:00:00"), INTERVAL 7 DAY) 
      AND DATE_SUB(DATE_FORMAT(@horafin, "%Y-%m-%d %H:00:00"), INTERVAL 7 DAY) 

ho questo in spiegare

id select_type table    type possible_keys key  key_len ref  rows Extra   
------ ----------- ----------------- ------ ------------- ------ ------- ------ ------- ------------- 
1 SIMPLE  ClientesHora_copy ALL  (NULL)   (NULL) (NULL) (NULL) 2716460 Using where 

Ma se non uso la variabile @sitio (ma uso le variabili @horaini, @horafin):

EXPLAIN SELECT nodo,sit,clientes,segundos,llamadas,fecha,hora,@horaini AS horaini,@horafin AS horafin 
     FROM `ClientesHora_copy` 
     WHERE 
     nodo ='ABA000' 
     AND 
     fecha BETWEEN DATE_SUB(DATE_FORMAT(@horaini, "%Y-%m-%d %H:00:00"), INTERVAL 7 DAY) 
      AND DATE_SUB(DATE_FORMAT(@horafin, "%Y-%m-%d %H:00:00"), INTERVAL 7 DAY) 

ottengo questo:

id select_type  table    type possible_keys key   key_len ref  rows Extra 
------ ----------- ----------------- ------ --------------- ---------- ------- ------ ------ ------------- 
1 SIMPLE   ClientesHora_copy range nodo_fecha,nodo nodo_fecha 18  (NULL)  1 Using where 

Qualsiasi idea del perché Mysql doesnt utilizzare l'indice con la variabile @sitio ma lo fa con @fechaini e @fechafin?

Grazie!

+2

Il problema non è la mancanza di un valore "costante" (come indica la risposta selezionata. È abbastanza facile dimostrare che MySQL utilizzerà un indice "const" con una variabile utente. Il problema è il set di caratteri; la variabile utente è probabilmente un set di caratteri diverso dalla colonna. Possiamo usare la funzione 'CONVERT()' per convertire tra diversi set di caratteri. – spencer7593

risposta

8

La spiegazione più probabile è che la colonna nodo sia un tipo di dati carattere e character_set_connection non corrisponda al set di caratteri specificato per la colonna.

Se la colonna è definita con latin1 di caratteri, provare:

WHERE nodo = CONVERT(@sitio USING latin1) 

A dimostrazione, con utf8, spiegare output mostra alcun indice disponibili:

EXPLAIN SELECT t.* FROM mytable t WHERE t.foo = CONVERT(@foo USING utf8) 
                    ^^^^ 
id select_type table type possible_keys key key_len ref rows Extra   
-- ----------- ----- ---- ------------- ------ ------- ------ ---- ----------- 
1 SIMPLE  t  ALL (NULL)  (NULL) (NULL) (NULL) 3 Using where 

Ma con latin1, spiegare l'output mostra l'indice è disponibile (ed è utilizzato):

EXPLAIN SELECT t.* FROM mytable t WHERE t.foo = CONVERT(@foo USING latin1) 
                    ^^^^^^  
id select_type table type possible_keys key key_len ref rows Extra   
-- ----------- ----- ---- ------------- ------ ------- ------ ---- ----------- 
1 SIMPLE  t  ref t_ix   t_ix 13  const  1 Using where 
+1

apparentemente questo era il problema, ho cambiato la dichiarazione della variabile in SET @ sitio = CONVERT ('AA000' USING latin1); e la query è ora VERAMENTE veloce. Grazie! – Alejandro

+0

Grazie, ha risolto anche il mio problema! –

Problemi correlati