划分指的是將邏輯上的一個大表分成一些小的物理上的片。划分有很多益處:
1、在某些情況下查詢性能能夠顯著提升,特別是當那些訪問壓力大的行在一個分區或者少數幾個分區時。划分可以取代索引的主導列、減小索引尺寸以及使索引中訪問壓力大的部分更有可能被放在內存中。
2、當查詢或更新訪問一個分區的大部分行時,可以通過該分區上的一個順序掃描來取代分散到整個表上的索引和隨機訪問,這樣可以改善性能。
3、如果需求計划使用划分設計,可以通過增加或移除分區來完成批量載入和刪除。ALTER TABLE NO INHERIT和DROP TABLE都遠快於一個批量操作。這些命令也完全避免了由批量DELETE造成的VACUUM負載。
4、很少使用的數據可以被遷移到便宜且較慢的存儲介質上。
當一個表非常大時,划分所帶來的好處是非常值得的。一個表何種情況下會從划分獲益取決於應用,一個經驗法則是當表的尺寸超過了數據庫服務器物理內存時,划分會為表帶來好處。
目前,PostgreSQL支持通過表繼承來進行划分。每一個分區被創建為父表的一個子表。父表本身通常是空的,它的存在僅僅為了表示整個數據集。
例如: select * from only tb_log,可以查看到主表並未存儲數據。
范圍划分
表被根據一個關鍵列或一組列划分為"范圍",不同的分區的范圍之間沒有重疊。例如,我們可以根據日期范圍划分,或者根據特定業務對象的標識符划分。
列表划分
通過顯式地列出每一個分區中出現的鍵值來划分表。
實現划分
1、創建分表並關聯主表(可以根據年份,季度和或者月份來創建分表)
例:表名為tb_log,createtime 表示tb_log的一個字段,記錄時間
CREATE TABLE tb_log_2017 ( CHECK ( createtime >= DATE '2017-01-01' AND createtime < DATE '2018-01-01' ) ) INHERITS (tb_log); CREATE TABLE tb_log_2018 ( CHECK ( createtime >= DATE '2018-01-01' AND createtime < DATE '2019-01-01' ) ) INHERITS (tb_log);
-- 這里創建了tb_log_2017 和 tb_log_2018 兩張分表.
** 這個語句創建的分表沒有主鍵,手動為每張分表加上主鍵
2、創建觸發器函數
CREATE OR REPLACE FUNCTION function_insert_tb_log() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.createtime >= DATE '2017-01-01' AND NEW.createtime < DATE '2018-01-01' ) THEN INSERT INTO tb_log_2017 VALUES (NEW.*); ELSIF ( NEW.createtime >= DATE '2018-01-01' AND NEW.createtime < DATE '2019-01-01' ) THEN INSERT INTO tb_log_2018 VALUES (NEW.*); ELSE RAISE EXCEPTION 'Date out of range. Fix the function_insert_tb_log() function!'; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
3、創建觸發器
CREATE TRIGGER trigger_insert_tb_log
BEFORE INSERT ON tb_log
FOR EACH ROW
EXECUTE PROCEDURE function_insert_tb_log();
備注:維護表的時候,只要執行第1步和第2步就可以了,比如到2019年的時候,再用第1步的格式去創建2019年的分表(tb_log_2019),然后修改一下第2步的邏輯,執行一下就可以了。
** 使用Hibernate的時候注意,hibernate的save方法有期待返回的保存結果,分表之后保存並不會返回保存結果,所以要在實體里加入下面這行代碼:
@SQLInsert(sql = "insert into tb_log (id,column1,column2) values (?,?,?)")