2013-01-25 57 views
1

失敗我用大(> 100萬行)表具有以下創建:MySQL的指數似乎在大表

data_values | CREATE TABLE `data_values` (
    `T` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `ID` varchar(32) NOT NULL, 
    `VAL` float DEFAULT NULL, 
    PRIMARY KEY (`T`,`ID`), 
    KEY `IX_d` (`ID`), 
    KEY `IX_T` (`T`) 
) ENGINE=InnoDB DEFAULT CHARSET=greek PACK_KEYS=1 ROW_FORMAT=DYNAMIC | 

我的查詢有以下幾種形式:

select t,id,val from data_values where t between "2013-01-11 02:47:02" and "2013-01-12 04:59:02" and id="815"; 

我問題是有時使用索引(並且答案非常快),有時它不被使用(並且答案在1-2分鐘內出現),並且我找不到任何邏輯。例如,下面的查詢是快:

select t,id,val from data_values where t between "2013-01-11 02:47:02" and "2013-01-13 04:59:02" and id="815"; 

而下面的查詢(其請求更少的數據,一天而不是兩個)是慢:

select t,id,val from data_values where t between "2013-01-11 02:47:02" and "2013-01-12 04:59:02" and id="815"; 

解釋查詢:

explain select t,id,value from data_values where t between "2013-01-11 02:47:02" and "2013-01-13 04:59:02" and id="815"; 
| id | select_type | table    | type  | possible_keys 
| key    | key_len | ref | rows | Extra 
      | 
+----+-------------+----------------------+-------------+----------------------- 
+-----------------+---------+------+------+------------------------------------- 
----------+ 
| 1 | SIMPLE  | data_values   | index_merge | PRIMARY,IX_D,IX_T 
| IX_D,PRIMARY  | 34,38 | NULL | 1033 | Using intersect(IX_D,PRIMARY); Us 
ing where | 
+----+-------------+----------------------+-------------+----------------------- 
+-----------------+---------+------+------+------------------------------------- 


explain select t,id,val from data_values where t between "2013-01-11 02:47:02" and "2013-01-12 04:59:02" and id="815"; 
+----+-------------+----------------------+------+-----------------------+------ 
---+---------+-------+--------+-------------+ 
| id | select_type | table    | type | possible_keys   | key 
    | key_len | ref | rows | Extra  | 
+----+-------------+----------------------+------+-----------------------+------ 
---+---------+-------+--------+-------------+ 
| 1 | SIMPLE  | data_values   | ref | PRIMARY,IX_D,IX_T  | IX_D   | 34  | const | 143900 | Using where | 
+----+-------------+----------------------+------+-----------------------+------ 
---+---------+-------+--------+-------------+ 

我不明白第一個查詢是如何「更廣泛」(要求更多數據)使用索引,而第二個查詢不是。搜索stackoverflow我發現了一些關於多列索引的答案。但是我已經使用了一個(我的主鍵),並且按照正確的順序(在查詢中,在變量前面提到了t變量)。我發現的另一個答案涉及OR查詢(做單獨的查詢和形成一個UNION),但我的查詢使用AND。

我需要我怎樣才能加快我的查詢,

感謝了很多的建議。

回答

0

您有一個索引(t, id)

你需要(id, t)指數以這種查詢,甚至更好,在(id, t, val)一個「覆蓋」指數:

ALTER TABLE data_values 
    DROP INDEX IX_T   -- the Primary Key is (t, id) so this index 
           -- is rather redundant. 
    , DROP INDEX IX_d   -- this was not redundant but it is now 
           -- (because of) 
    , ADD INDEX IX_ID_T_VAL  -- the new index 
     (id, t, value) ;