2017-02-27 126 views
3

我有一個表的字段,它是ACTION_TIME主鍵和類型爲datetimeMySQL分區不起作用

我試圖打破它的分區

ALTER TABLE foo PARTITION BY RANGE (MONTH(action_time)) 
(
PARTITION p01 VALUES LESS THAN (02) , 
PARTITION p02 VALUES LESS THAN (03) , 
PARTITION p03 VALUES LESS THAN (04) , 
PARTITION p04 VALUES LESS THAN (05) , 
PARTITION p05 VALUES LESS THAN (06) , 
PARTITION p06 VALUES LESS THAN (07) , 
PARTITION p07 VALUES LESS THAN (08) , 
PARTITION p08 VALUES LESS THAN (09) , 
PARTITION p09 VALUES LESS THAN (10) , 
PARTITION p10 VALUES LESS THAN (11) , 
PARTITION p11 VALUES LESS THAN (12) , 
PARTITION p12 VALUES LESS THAN (13) , 
PARTITION pmaxval VALUES LESS THAN MAXVALUE 
); 

在phpMyAdmin我看到行 分區,但當我執行

explain partitions select * from foo where action_time between '2017-01-01 20:34:08' and '2017-01-21 20:34:08'; 

explain partitions select * from foo where action_time > '2017-01-01 20:34:08' && action_time < '2017-01-21 20:34:08' 

它擊中所有分區(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,pmaxval)

什麼,我做錯了什麼?

我也嘗試這種方式的結果相同

ALTER TABLE foo 
    PARTITION BY RANGE( YEAR(action_time)) 
    SUBPARTITION BY HASH(MONTH(action_time)) 
    SUBPARTITIONS 12 (
    PARTITION p2015 VALUES LESS THAN (2016), 
    PARTITION p2016 VALUES LESS THAN (2017), 
    PARTITION p2017 VALUES LESS THAN (2018), 
    PARTITION p2018 VALUES LESS THAN (2019), 
    PARTITION p2019 VALUES LESS THAN (2020), 
    PARTITION p2020 VALUES LESS THAN (2021), 
    PARTITION p2021 VALUES LESS THAN (2022), 
    PARTITION p2022 VALUES LESS THAN (2023), 
    PARTITION p2023 VALUES LESS THAN (2024), 
    PARTITION p2024 VALUES LESS THAN (2025), 
    PARTITION p2025 VALUES LESS THAN (2026), 
    PARTITION p2026 VALUES LESS THAN (2027), 
    PARTITION p2027 VALUES LESS THAN (2028), 
    PARTITION p2028 VALUES LESS THAN (2029), 
    PARTITION p2029 VALUES LESS THAN (2030), 
    PARTITION pmax VALUES LESS THAN MAXVALUE 
); 

我需要按年份和月份打破錶提高選擇的時候,當我的日期之間選擇它sholdn't在全表搜索它應該在相關的分區中進行搜索。我怎樣才能做到這一點?

回答

1

您發現PARTITIONing幾乎沒用的另一個原因。

假設您已指定BETWEEN '2015-11-05' AND '2017-02-02'。它需要打哪個分區?他們全部。

假設您已指定BETWEEN '2015-11-05' AND '2016-02-02'。它需要打哪個分區? 4,但它不夠巧妙。所以它會(我認爲)全部擊中。

模式數量有限(MONTH()不是其中之一),其中分區將「正確」。

要使BY RANGE(some date)能夠正常工作,您僅限於BY RANGE(TO_DAYS(date))(以及其他幾個)。但是,你必須每個月都創建一個新的分區(或者經常)。並且,可選地,最老的分區是DROP

現在爲您計劃的另一個原因是可能無用。期望從分區中獲得什麼好處?也許表現?可能不會給你任何性能好處。讓我們看看您的查詢,以便我可以解釋原因。

簡單

SELECT ... 
    WHERE date >= '...' 
     AND date < '...' + INTERVAL 20 DAY 

將工作一樣快INDEX(date)與分區。可能更快。

如果WHERE中還有別的東西,那就改變了一切。

My PARTITION blog

爲什麼分區不加快簡單的查詢

比方說,你有一個簡單的SELECT,有一個很好的指標,如您指定PRIMARY KEY精確值。 (這稱爲「點查詢」。)

情況1:非分區表。索引使用BTree結構。定位一百萬行中的特定記錄需要深入挖掘BTree,該深度約爲3級。對於十億行,它可能是5個級別。

案例2:分區表。分區將表分成多個表,每個表都有索引。找到一個特定的行首先必須找到特定的分區(子表),然後向下鑽取該分區的較淺的BTree。

想想如果它(或許)從BTree中移除一個等級,但是增加了達到分區的額外努力。性能差異很小。目前尚不清楚你是贏或輸。 (緩存,數據結構等使分析變得複雜)。

結論:對於點查詢,假設您在非分區等價物上有合適的索引,分區永遠不會有幫助。

你的特定查詢是一個簡單的 「範圍」 的查詢:WHERE action_time BETWEEN ... AND ...

最佳表結構(包括分區和索引)是

  • 沒有分區
  • INDEX(action_time)

另一個注意:如果涉及多個分區,則SELECT將從eac中提取行(如果有的話) h分區(修剪後),將它們放在一起,然後可能必須對結果進行排序(取決於SELECT中的其他子句)。唉,在執行查詢時沒有並行性,所以分區變量更多地涉及,因此可能會更慢。

+0

還有一些更多的規則,如type ='...'和m_id ='...' 這個表很大,它充滿了大量的日常記錄 我認爲分區加速選擇 – David

+0

而且,與您的新的編輯,你已經找到了一個爲什麼我說'SUBPARTITION'沒用的例子。 –

+0

我在回答中添加了「爲什麼分區不會加速簡單查詢」。 –