11

我有这张桌子:

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 =@sitio
        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 吗?

谢谢!

4

1 回答 1

19

最可能的解释是该列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
于 2013-02-22T20:42:53.430 回答