2011-11-03 47 views
1

我有一個表'fvs_data',帶有我用於分區的時間戳列。如果我有一個複雜的查詢,查詢優化器似乎沒有選擇正確的分區。例如,該查詢MySQL分區選擇沒有正確優化

EXPLAIN PARTITIONS SELECT * FROM `fvs_data` WHERE `timestamp` = '2011-11-02' 

使用正確的分區,如在顯示分區列表:p_2011_44,由於TO_DAYS( '2011-11-02')= 734808。

但如果添加應該返回完全相同的分區的另一個條件,那麼它要檢查其他分區

EXPLAIN PARTITIONS SELECT * FROM `fvs_data` WHERE `timestamp` > '2011-11-01' AND `timestamp` < '2011-11-03' 

它返回p_2011_42,p_2011_44的分區列表中的一個。這裏是我的CREATE TABLE語法

CREATE TABLE `fvs_data` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`fvs_client_id` int(11) NOT NULL, 
`timestamp` datetime NOT NULL, 
`setupid` char(20) NOT NULL, 
`assyline` char(20) NOT NULL, 
`machine` char(20) NOT NULL, 
`side` char(20) NOT NULL, 
`module` char(20) NOT NULL, 
`fixtureid` char(20) NOT NULL, 
`fixturepos` char(20) NOT NULL, 
`feedpos` char(20) NOT NULL, 
`partnum` char(20) NOT NULL, 
`vendor` char(20) NOT NULL, 
`tid` char(20) NOT NULL, 
`quant` char(20) NOT NULL, 
`status` char(32) NOT NULL, 
`oper` char(20) NOT NULL, 
`lane1` char(20) NOT NULL, 
`lane2` char(20) NOT NULL, 
`sn` char(20) NOT NULL, 
`totalcomp` char(20) NOT NULL, 
PRIMARY KEY (`id`,`timestamp`), 
KEY `fvs_client_id` (`fvs_client_id`), 
KEY `setupid` (`setupid`), 
KEY `assyline` (`assyline`), 
KEY `machine` (`machine`), 
KEY `side` (`side`), 
KEY `module` (`module`), 
KEY `fixtureid` (`fixtureid`), 
KEY `fixturepos` (`fixturepos`), 
KEY `feedpos` (`feedpos`), 
KEY `partnum` (`partnum`), 
KEY `vendor` (`vendor`), 
KEY `tid` (`tid`), 
KEY `status` (`status`), 
KEY `oper` (`oper`), 
KEY `lane1` (`lane1`), 
KEY `lane2` (`lane2`), 
KEY `sn` (`sn`) 
) ENGINE=MyISAM AUTO_INCREMENT=36032 DEFAULT CHARSET=latin1 
/*!50100 PARTITION BY RANGE (TO_DAYS(timestamp)) 
(PARTITION p_2011_42 VALUES LESS THAN (734796) ENGINE = MyISAM, 
PARTITION p_2011_43 VALUES LESS THAN (734803) ENGINE = MyISAM, 
PARTITION p_2011_44 VALUES LESS THAN (734810) ENGINE = MyISAM, 
PARTITION p_2011_45 VALUES LESS THAN (734817) ENGINE = MyISAM) */ 

我試圖做每週的分區,而不是基於起始星期日真正星期,我只是除以7年的一天,並使用了創建一個分區名。

回答

0

分區修剪將始終檢查第一個分區,而不管您正在搜索的值如何。這與分區stores NULLs in the first partition的方式有關。

要解決這一點,並優化範圍分區,創建值的初始分區不到任何你通常會店:

... 
PARTITION BY RANGE (TO_DAYS(timestamp)) 
(
PARTITION p_0000 VALUES LESS THAN (0) ENGINE = MyISAM, -- NULLs end up here 
PARTITION p_2011_42 VALUES LESS THAN (734796) ENGINE = MyISAM, 
PARTITION p_2011_43 VALUES LESS THAN (734803) ENGINE = MyISAM, 
PARTITION p_2011_44 VALUES LESS THAN (734810) ENGINE = MyISAM, 
PARTITION p_2011_45 VALUES LESS THAN (734817) ENGINE = MyISAM 
PARTITION p_MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM 
) 

當然你timestamp列是NOT NULL,這樣第一個分區是空的,因此很快搜索。

P.S .:你還應該添加一個分區來捕獲任何其他分區範圍之外的任何大值。否則插入這樣的行將失敗。

+0

謝謝!我的軟件實際上是動態地添加新的分區,以便下一週的數據分區在有數據之前總是準備好。它還修剪比某些數據限制更早的分區。 – Matt

+0

理解,但我更喜歡保留一個MAXVALUE分區,以防萬一插入錯誤的值。也許你想要失敗,也許你想讓它成功。 –