2013-02-22 21 views
7

Tôi có bảng này:Mysql truy vấn dont't sử dụng chỉ số khi có biến trong ĐÂU

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 

và truy vấn này:

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) 

tôi có trong này giải thích

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 

Nhưng nếu tôi không sử dụng biến @sitio (nhưng sử dụng biến @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) 

tôi có được điều này:

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 

Bất kỳ ý tưởng về lý do tại sao Mysql doesnt sử dụng các chỉ số với @sitio biến nhưng nó có @fechaini và @fechafin?

Cảm ơn!

+2

Vấn đề không phải là thiếu giá trị "không đổi" (như câu trả lời đã chọn cho biết. Khá dễ dàng để chứng minh rằng MySQL sẽ sử dụng một chỉ mục "const" ref với biến người dùng. Vấn đề là bộ ký tự; biến người dùng có thể là một ký tự khác với cột. Chúng ta có thể sử dụng hàm 'CONVERT()' để chuyển đổi giữa các bộ ký tự khác nhau. – spencer7593

Trả lời

8

Giải thích rất có thể là cột nodo là kiểu dữ liệu ký tự và character_set_connection không khớp với bộ ký tự được chỉ định cho cột.

Nếu cột được định nghĩa với latin1 characterset, hãy thử:

WHERE nodo = CONVERT(@sitio USING latin1) 

Như một cuộc biểu tình, với utf8, giải thích kết quả cho thấy không có chỉ số có sẵn:

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 

Nhưng với latin1, đầu ra giải nghĩa cho thấy chỉ mục có sẵn (và được sử dụng):

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

dường như đó là vấn đề, tôi đã thay đổi khai báo biến thành SET @ sitio = CONVERT ('AA000' SỬ DỤNG latin1); và truy vấn bây giờ thực sự nhanh. Cảm ơn! – Alejandro

+0

Cảm ơn, điều đó đã giải quyết được vấn đề của tôi! –

Các vấn đề liên quan