??表分區是將?個表的數據按照?定的規則?平劃分為不同的邏輯塊,并分別進?物理存儲,這個規則就叫做分區函數,可以有不同的分區規則。5.7可以通過show plugins語句查看當前MySQL是否?持表分區功能。
鐵西網站制作公司哪家好,找創新互聯!從網頁設計、網站建設、微信開發、APP開發、自適應網站建設等網站項目制作,到程序開發,運營維護。創新互聯于2013年開始到現在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選創新互聯。
??但當表中含有主鍵或唯?鍵時,則每個被?作 分區函數的字段必須是表中唯?鍵和主鍵的全部或?部分 ,否則就?法創建分區表。?如下?的表由于唯?鍵和主鍵沒有相同的字段,所以?法創建表分區
上述例?中刪除唯?鍵,確保主鍵中的字段包含分區函數中的所有字段,創建成功
或者將主鍵擴展為包含ref字段
表分區的主要優勢在于:
??可以允許在?個表?存儲更多的數據,突破磁盤限制或者?件系統限制
??對于從表?將過期或歷史的數據移除在表分區很容易實現,只要將對應的分區移除即可
??對某些查詢和修改語句來說,可以 ?動 將數據范圍縮?到?個或?個表分區上,優化語句執?效率。?且可以通過 顯示指定表分區 來執?語句,?如 SELECT * FROM t PARTITION (p0,p1) WHERE c 5
表分區類型分為:
范圍表分區,按照?定的范圍值來確定每個分區包含的數據,分區函數使?的字段必須只能是 整數類型,分區的定義范圍必須是連續的,且不能有重疊部分,通過使?VALUES LESS THAN來定義分區范圍,表分區的范圍定義是從?到?定義的
?如:
??Store_id6的數據被放在p0分區?,6=store_id10之間的數據被放在p1分區?,以此類推,當新插?的數據為(72, ‘Mitchell’, ‘Wilson’, ‘1998-06-25’, NULL, 13) 時,則新數據被插?到p2分區?,但當插?的數據的store_id為21時,由于沒有分區去容納此數據,所以會報錯,我們需要修改?下表的定義
報錯:
修改表的定義:
?? MAXVALUE關鍵詞的作?是表示可能的最?值,所以任何store_id=16的數據都會被寫?到p3分區?。分區函數中也可以使?表達式 ,?如:
?? 對timestamp字段類型可以使?的表達式?前僅有unix_timestamp ,其他的表達式都不允許
列表表分區,按照?個?個確定的值來確定每個分區包含的數據,通過PARTITION BY LIST(expr)分區函數表達式必須返回整數,取值范圍通過VALUES IN (value_list)定義
對List表分區來說,沒有MAXVALUE特殊值,所有的可能取值都需要再VALUES IN中包含,如果有未定義的取值則會報錯
同樣,當有主鍵或者唯?鍵存在的情況下,分區函數字段需要包含在主鍵或唯?鍵中
對range和list表分區來說,分區函數可以包含多個字段,分區多字段函數(column partition) 所涉及的字段類型可以包括:
范圍多字段分區函數與普通的范圍分區函數的區別在于:
a) 字段類型多樣化
b) 范圍多字段分區函數 不?持表達式,只能?字段名
c) 范圍多字段分區函數?持?個或多個字段
再?如創建如下的表分區:
對多列對?來說:
當然只要保證取值范圍是增?的,表分區就能創建成功,?如:
但如果 取值范圍不是增?的,就會返回錯誤 :
對其他數據類型的?持:
list列表多字段表分區,例如:你有一個在12個城市客戶的業務, 為了銷售和市場的目的, 你的組織每3個城市劃分為一個區域針對LIST COLUMNS分區, 你可以基于城市的名稱創建一個客戶數據表并聲明4個分區當你的客戶在對應的這個區域:
使用日期分區
但是這種情況在日期增長到非常大的時候是很復雜的, 所以這種還是使用RANGE 分區方式比較好
??按照?個?定義的函數返回值來確定每個分區包含的數據,這個 ?定義函數也可以僅僅是?個字段名字
??通過PARTITION BY HASH (expr)?句來表達哈希表分區,其中的 expr表達式必須返回?個整數,基于分區個數的取模(%)運算。根據余數插?到指定的分區
??對哈希表分區來說只需要定義分區的個數,其他的事情由內部完成
如果沒有寫明PARTITIONS字段,則默認為1,表達式可以是整數類型字段,也可以是?個函數,?如
?如: CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY HASH( YEAR(col3) ) PARTITIONS 4;
如果插??條數據對應的col3為‘2005-09-15’時,則插?數據的分區計算?法為:
??與哈希表分區類似,只不過哈希表分區依賴于?定義的函數,?key表分區的哈希算法是依賴MySQL本身, CREATE TABLE ... PARTITION BY KEY () 創建key表分區, 括號??可以包含0個或者多個字段,所引?的字段必須是主鍵或者主鍵的?部分 ,如果括號??沒有字段,則代表使?主鍵
如果表中沒有主鍵但有唯?鍵,則使?唯?鍵,但 唯?鍵字段必須定義為not null ,否則報錯
所引?的字段未必必須是整數類型,其他的類型也可以使?,?如:
?表分區,是在表分區的基礎上再創建表分區的概念, 每個表分區下的?表分區個數必須?致 ,?如:
ts表擁有三個范圍分區,同時每個分區都各?有兩個?分區,所以總共有6個分區
?表分區必須是范圍/列表分區+哈希/key?表分區的組合
?表分區也可以顯示的指定?表分區的名字,?如:
不同的表分區對NULL值的處理?式不同
對范圍表分區來說,如果插?的是NULL值,則將數據放到最?的分區表?
對list表分區來說,?持NULL值的唯?情況就是某個分區的允許值中包含NULL
對哈希表分區和Key表分區來說,NULL值會被當成0值對待
通過alter table命令可以執?增加,刪除,重新定義,合并或者拆分表分區的管理動作
對范圍表分區和列表表分區來說,刪除?個表分區命令如下:
刪除表分區的動作不光會把分區刪掉,也會把表分區?原來的數據給刪除掉
在原分區上增加?個表分區可以通過alter table … add partition語句來完成
但對范圍表分區來說,增加的表分區必須在尾部增加,在頭部或者在中間增加都會失?。?/p>
為解決這個問題,可以使? REORGANIZE 命令:
對列表表分區來說,只要新增加的分區對應的值在之前的表分區中沒有出現過,就可以通過alter table… add partition來增加
當然, 也可以通過REORGANIZE命令將之前的多個分區合并成?個或?個分區,但要保持分區值?致:
更復雜的?如將多個分區重組成多個分區:
一、背景
話說風和日麗的一天,為提高隨著業務增長的大表(3510449行吧)的訪問效率,于是決定對表分區,記錄如下。
二、實操
結合業務,若干條記錄會集中在一個日期,查詢時也往往只查詢一個日期內的數據,于是選取分區字段為時間。
創建分區 比如
CREATE TABLE message_all (
id int(10) NOT NULL AUTO_INCREMENT,
......
createtime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間'
PRIMARY KEY ( id , createtime )
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE (YEAR(createtime))
(PARTITION p2015 VALUES LESS THAN (2016) ENGINE = InnoDB,
PARTITION p2016 VALUES LESS THAN (2017) ENGINE = InnoDB,
PARTITION p2017 VALUES LESS THAN (2018) ENGINE = InnoDB,
PARTITION p2018 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)
不過我們表已經有了當然不能這么建,除非你想導一次數據。
如下操作 :
1、
ALTER TABLE message_all PARTITION BY RANGE (to_days(createtime))
(
PARTITION p2015 VALUES LESS THAN (to_days('2016-01-01')),
PARTITION p2016 VALUES LESS THAN (to_days('2017-01-01')),
PARTITION p2017 VALUES LESS THAN (to_days('2018-01-01')),
PARTITION p2018 VALUES LESS THAN MAXVALUE
);
或者
2、ALTER TABLE message_all PARTITION BY RANGE (YEAR(createtime))
(
PARTITION p2015 VALUES LESS THAN (YEAR('2016-01-01'))
);
然后追加。
ALTER TABLE message_all ADD PARTITION
(
PARTITION p2016 VALUES LESS THAN (YEAR('2017-01-01')),
PARTITION p2017 VALUES LESS THAN (YEAR('2018-01-01')),
PARTITION p2018 VALUES LESS THAN MAXVALUE
);
這里會有幾種錯誤情況:
1、ALTER TABLE message_all PARTITION BY RANGE (to_days(createtime)) ;
[Err] 1492 - For RANGE partitions each partition must be defined
解釋:必須指定至少一個分區。
2、[Err] 1492 - A PRIMARY KEY must include all columns in the table's partitioning function
解釋:分區字段必須是主鍵之一。
3、[Err] 1492 - Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
解釋:分區字段為timestamp,換成datetime。
4、[Err] 1526 - Table has no partition for value xxxx
解釋:用追加方式第一次必須覆蓋目前所有數據。
總結:
1、創建時必須指定至少一個分區。
2、key必須為主鍵之一。
3、RANGE處必須為INT型,時間字段用函數轉——YEAR()、YEARWEEK()、TO_DAYS()。
4、THAN處必須為INT型,時間字段用函數轉——TO_DAYS、TO_SECONDS()、UNIX_TIMESTAMP()。
5、它就是以兩個INT比大小劃分的文件。
6、所有ENGINE必須一樣。
7、范圍分區添加只能在最大值后面追加。
8、分區是有上限的貌似1024個。
用到的其他操作
1、刪除分區(直接扔掉分區文件,數據也沒了)
ALTER TABLE message_all DROP PARTITION p2016;
2、清空分區數據
ALTER TABLE message_all TRUNCATE PARTITION p2017;
3、重定義(可實現:分區拆分、合并、重命名)
ALTER TABLE message_all REORGANIZE PARTITION p201601,p201602,p201603,p201604 INTO
(
PARTITION p2016012 VALUES less than(TO_DAYS('2016-03-01')),
PARTITION p2016034 VALUES less than(TO_DAYS('2016-05-01'))
);
檢查/查看你的分區
1、SHOW TABLE STATUS LIKE 'message_all';
2、SELECT * FROM information_schema.partitions WHERE table_name='message_all';
3、SHOW CREATE TABLE message_all;
4、EXPLAIN SELECT COUNT(1) FROM message_all WHERE createtime= '2016-01-01' AND createtime '2016-12-30';如果用到了分區partitions里會有顯示。
5、指定分區查
SELECT COUNT(1) FROM message_all PARTITION (p2016) 表別名 WHERE ......;
到這里就結束啦,土豆白。
一些概念
水平分區Partition有以下幾種模式
對底層表的封裝,意味著索引也是按照分區的子表定義的,而沒有全局索引。(所以即使有唯一性索引,在不同子表中可能會有重復數據)
單表數據量超大時索引失效
將單表分區成數個區域,通過分區函數,可以快速地定位到數據的區域。而且相比于索引,分區不需要額外的數據結構記錄每個分區的數據,代價更低。只需要一個簡單的表達式就可以指向正確的分區
可以只是用簡單的分區方式存放表,不要任何索引,只要將查詢定位到需要的大致數據位置,通過where條件,將需要的數據限制在少數分區中,則效率是很高的。WARNNING:查詢需要掃描的分區個數限制在一個很小的數量。
如果數據有明顯的“熱點”,可以將熱點數據單獨放在一個分區,讓這個分區的數據能夠有機會都緩存在內存中。
如果分區表達式的值可以是NULL:第一個分區會使一個特殊分區。以partition by range year(order_date)為例,所有在order_date列為NULL或者非法值的數據都會被放到第一個分區。那么所有的查詢在定位分區后都會增加掃描第一個分區。而且如果第一個分區很大的時候,查詢的成本會被這個“拖油瓶”分區無情的增加。
創建一個無用的第一分區可以解決這個問題,partition p_nulls values less than (0);
對于分區列和索引列不匹配的查詢,雖然查詢能夠使用索引,但是無法通過分區定位到目標數據的分區(也就是數據分布相對更加分散),需要遍歷每個分區內的索引,除非查詢中的條件同時也包含分區條件。所以期望分區條件范圍被熱門查詢索引所包含。
對于 范圍分區 技術,需要適當限制分區的數量,否則對于大量數據批量導入的場景,選擇分區的成本過高。對于大多數系統,100個左右的分區是沒有問題的。
我們的業務只存近一段時間的數據,因此有大量表需要清理 歷史 數據,目前使用的delete清理數據,存在以下問題。為避免同時支持大量delete,我們的清理任務只在低峰期串行執行,導致任務過多時需要排隊,甚至失敗的情況;數據清理使用delete語句,表數據量較大時,對數據庫造成很大壓力;即使我們刪除了舊數據,已刪除的數據仍占據存儲空間,底層數據文件并沒有立刻變小,以至于形成數據空洞。
查看MySQL官方文檔時,發現了分區表,因此基于官方文檔總結一下。
MySQL邏輯上為一個表,物理上存儲在多個文件中,這是 MySQL 支持的功能(5.1 開始), 8.0 版本只 InnoDB 和 NDB 支持分區表。
優點:
缺點:
根據分區表鍵值的范圍把數據存儲到表的不同分區中,適用于以時間或日期作為分區類型,方便數據清理。
小提示:
1.當插入數據分區不存在時會報錯:Table has no partition for value xxx;
2.Range類型分區字段必須是數值,時間類型可用函數轉換為數值;
3.分區字段列值可以為null,所有為null的數據將存在最小的分區中;
按分區鍵取值的列表進行分區,每一行數據須找到對應的分區列表,否則數據插入失敗
小提示:
根據指定分區表達式的整數值以及分區數進行數據劃分(mod函數)
小提示:
按鍵分區類似于按哈希分區,只是哈希分區使用用戶定義的表達式,用于鍵分區的哈希函數由 MySQL 服務器提供。NDB 集群為此使用 MD5() ; 對于使用其他存儲引擎的表,服務器使用自己的內部哈希函數。
小提示:
子分區(subpartitioning)也稱為復合分區(composite partitioning) ,是已分區表中每個分區的進一步劃分
小提示:
小提示:
以下是創建一張測試表TEST并且按照時間CREATE_TIME創建RANGE分區,并使用ID創建hash分區,組成復合分區。
CREATE TABLE TEST (
CREATE_TIME DATETIME DEFAULT NULL, ID BIGINT(15) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8
PARTITION BY RANGE(TO_DAYS(CREATE_TIME)) PARTITIONS 7 SUBPARTITION BY HASH(ID) SUBPARTITIONS 16
(PARTITION P1710 VALUES LESS THAN (TO_DAYS ('2017-10-01'))
(SUBPARTITION P1710sp0 ,SUBPARTITION P1710sp1 ,
SUBPARTITION P1710sp2 ,SUBPARTITION P1710sp3 ,
SUBPARTITION P1710sp4 ,SUBPARTITION P1710sp5 ,
SUBPARTITION P1710sp6 ,SUBPARTITION P1710sp7 ,
SUBPARTITION P1710sp8 ,SUBPARTITION P1710sp9 ,
SUBPARTITION P1710sp10 ,SUBPARTITION P1710sp11 ,
SUBPARTITION P1710sp12 ,SUBPARTITION P1710sp13 ,
SUBPARTITION P1710sp14 ,SUBPARTITION P1710sp15 ),
PARTITION P1711 VALUES LESS THAN (TO_DAYS ('2017-11-01'))
(SUBPARTITION P1711sp0 ,SUBPARTITION P1711sp1 ,
SUBPARTITION P1711sp2 , SUBPARTITION P1711sp3 ,
SUBPARTITION P1711sp4 , SUBPARTITION P1711sp5 ,
SUBPARTITION P1711sp6 , SUBPARTITION P1711sp7 ,
SUBPARTITION P1711sp8 , SUBPARTITION P1711sp9 ,
SUBPARTITION P1711sp10 , SUBPARTITION P1711sp11 ,
SUBPARTITION P1711sp12 , SUBPARTITION P1711sp13 ,
SUBPARTITION P1711sp14 , SUBPARTITION P1711sp15 ),
名稱欄目:mysql表怎么分區 mysql的表分區
分享網址:http://vcdvsql.cn/article28/heppjp.html
成都網站建設公司_創新互聯,為您提供網站維護、電子商務、全網營銷推廣、定制開發、App開發、標簽優化
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯