2012年3月21日 星期三

提昇資料庫效率的方法:Partition

原本要找的是 AUTO_INCREMENT 爆掉的問題該怎麼處理
意外找到這個可以提昇資料庫效率的方法~
詳細說明可以直接看下列的參考資料

參考資料:
1、通過分區(Partition)提升MySQL性能(一)
2、通過分區(Partition)提升MySQL性能(二)
3、mysql 的 partition 與 auto_increment

在 [1] 的效能測試中,建了兩個資料表,一個使用 Partition、一個沒使用
然後用隨機產生的資料填入 800 萬筆資料,測試找出時間是 1995 年間的所有資料
在沒有做 Partition 的資料表中花了 38 秒,有做 Partition 的則只花了 3 秒多~
當資料有顯著的分區效果時,做 Partition 可以降低搜尋資料的時間~

不過後來又找到 [3],同時使用 AUTO_INCREMENT 跟 Partition 時 MySQL 可能會有問題....
目前暫定的作法是使用 Partition、放棄 AUTO_INCREMENT
用其他 INDEX 來盡可能達到類似 AUTO_INCREMENT 的 PRIMARY KEY 效果~


附錄1:我用的 SQL statement

CREATE TABLE  `house_object` (
  `object_timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE = MYISAM 
PARTITION BY RANGE (year(object_timestamp)) (
  PARTITION p1 VALUES LESS THAN( 2012 ) ,
  PARTITION p2 VALUES LESS THAN( 2013 ) ,
  PARTITION p3 VALUES LESS THAN( 2014 ) ,
  PARTITION p4 VALUES LESS THAN( 2015 ) ,
  PARTITION p5 VALUES LESS THAN( 2016 ) ,
  PARTITION p6 VALUES LESS THAN( 2017 ) ,
  PARTITION p7 VALUES LESS THAN( 2018 ) ,
  PARTITION p8 VALUES LESS THAN( 2019 ) ,
  PARTITION p9 VALUES LESS THAN( 2020 ) ,
  PARTITION p10 VALUES LESS THAN( 2021 ) ,
  PARTITION p11 VALUES LESS THAN( 2022 ) ,
  PARTITION p12 VALUES LESS THAN( 2023 ) ,
  PARTITION p13 VALUES LESS THAN( 2024 ) ,
  PARTITION p14 VALUES LESS THAN( 2025 ) ,
  PARTITION p15 VALUES LESS THAN( 2026 ) ,
  PARTITION p16 VALUES LESS THAN( 2027 ) ,
  PARTITION p17 VALUES LESS THAN( 2028 ) ,
  PARTITION p18 VALUES LESS THAN( 2029 ) ,
  PARTITION p19 VALUES LESS THAN( 2030 ) ,
  PARTITION p20 VALUES LESS THAN( 2031 ) ,
  PARTITION p21 VALUES LESS THAN MAXVALUE
);

附錄2:在我的實機(ubuntu 11.10)上發現 ubuntu 目前的 MySQL 版本 5.1.61-0ubuntu0.11.10.1 不支援使用 timestamp 來做 Partition,所以必須改成別的方法,我的作法是改用 Java 的 Date.getTime() 取得的數字來做 Partition。

CREATE TABLE IF NOT EXISTS house_object (
PARTITION BY RANGE (object_timestamp) (
  object_timestamp INT NOT NULL
)
PARTITION BY RANGE (object_timestamp)
(
  PARTITION partition1 VALUES LESS THAN (1325347200000) ENGINE = MyISAM, 
  PARTITION partition2 VALUES LESS THAN (1356969600000) ENGINE = MyISAM, 
  PARTITION partition3 VALUES LESS THAN (1388505600000) ENGINE = MyISAM, 
  PARTITION partition4 VALUES LESS THAN (1420041600000) ENGINE = MyISAM, 
  PARTITION partition5 VALUES LESS THAN (1451577600000) ENGINE = MyISAM, 
  PARTITION partition6 VALUES LESS THAN (1483200000000) ENGINE = MyISAM, 
  PARTITION partition7 VALUES LESS THAN (1514736000000) ENGINE = MyISAM, 
  PARTITION partition8 VALUES LESS THAN (1546272000000) ENGINE = MyISAM, 
  PARTITION partition9 VALUES LESS THAN (1577808000000) ENGINE = MyISAM, 
  PARTITION partition10 VALUES LESS THAN (1609430400000) ENGINE = MyISAM, 
  PARTITION partition11 VALUES LESS THAN (1640966400000) ENGINE = MyISAM, 
  PARTITION partition12 VALUES LESS THAN (1672502400000) ENGINE = MyISAM, 
  PARTITION partition13 VALUES LESS THAN (1704038400000) ENGINE = MyISAM, 
  PARTITION partition14 VALUES LESS THAN (1735660800000) ENGINE = MyISAM, 
  PARTITION partition15 VALUES LESS THAN (1767196800000) ENGINE = MyISAM, 
  PARTITION partition16 VALUES LESS THAN (1798732800000) ENGINE = MyISAM, 
  PARTITION partition17 VALUES LESS THAN (1830268800000) ENGINE = MyISAM, 
  PARTITION partition18 VALUES LESS THAN (1861891200000) ENGINE = MyISAM, 
  PARTITION partition19 VALUES LESS THAN (1893427200000) ENGINE = MyISAM, 
  PARTITION partition20 VALUES LESS THAN (1924963200000) ENGINE = MyISAM, 
  PARTITION partition21 VALUES LESS THAN MAXVALUE ENGINE = MyISAM
);

這樣的效果跟前面是一樣的,以一年做分區,不過每次 INSERT 時都要自己指定 object_timstamp 的值。

沒有留言: