2013-02-22 54 views
7

我有这样的表变量:MySQL查询dont't使用索引时,有在WHERE

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 

与此查询:

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) 

我有这样的解释

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 

但是,如果我不使用@sitio变量(但使用@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) 

我得到这个:

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 

为什么mysql的犯规使用索引与@sitio变量的任何想法,但它与@fechaini和@fechafin呢?

谢谢!

+2

问题不在于缺少“常量”值(因为所选答案指示。这很容易证明MySQL将使用带用户变量的索引“const”ref。问题是字符集;用户变量可能与列不同。我们可以使用'CONVERT()'函数可以用来在不同的字符集之间进行转换。 – spencer7593 2013-02-22 21:39:45

回答

8

最可能的解释是列nodo是字符数据类型,并且character_set_connection与为该列指定的字符集不匹配。

如果列与latin1字符集定义,请尝试:

WHERE nodo = CONVERT(@sitio USING latin1) 

作为示范,以UTF8,解释输出显示没有可用的指标:

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 

但随着LATIN1,解释输出显示索引是可用的(并且被使用):

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

显然这是问题所在,我将变量声明更改为SET @ sitio = CONVERT('AA000'USING latin1);并且查询现在非常快速。谢谢! – Alejandro 2013-02-22 21:35:50

+0

谢谢,这也解决了我的问题! – 2016-03-13 00:23:46