mysql從5.1版本開始支持分區功能。MySQL5.1中分區表達式必須是整數,或者返回整數的表達式;而MySQL5.5中提供了非整數表達式分區的支持。MySQL數據庫的分區是局部分區索引,一個分區中既存了數據,又放了索引;也就是說,每個區的聚集索引和非聚集索引都放在各自區的(不同的物理文件)。MySQL支持4種分區類型:RANGE分區,LIST分區,HASH分區,KEY分區。
本教程操作環境:windows7系統、mysql8版本、Dell G3電腦。
mysql支持分區。
mysql分區概述
MySQL在5.1時添加了對水平分區的支持。分區是將一個表或索引分解成多個更小,更可管理的部分。每個區都是獨立的,可以獨立處理,也可以作為一個更大對象的一部分進行處理。這個是MySQL支持的功能,業務代碼無需改動。要知道MySQL是面向OLTP的數據,它不像tidb等其他DB。那么對于分區的使用應該非常小心,如果不清楚如何使用分區可能會對性能產生負面的影響。
MySQL數據庫的分區是局部分區索引,一個分區中既存了數據,又放了索引。也就是說,每個區的聚集索引和非聚集索引都放在各自區的(不同的物理文件)。目前MySQL數據庫還不支持全局分區。
無論哪種類型的分區,如果表中存在主鍵或唯一索引時,分區列必須是唯一索引的一個組成部分。
分區表的限制因素
(1)、一個表最多只能有1024個分區。
(2)、 MySQL5.1中,分區表達式必須是整數,或者返回整數的表達式。在MySQL5.5中提供了非整數表達式分區的支持。
(3)、如果分區字段中有主鍵或者唯一索引的列,那么多有主鍵列和唯一索引列都必須包含進來。即:分區字段要么不包含主鍵或者索引列,要么包含全部主鍵和索引列。
(4)、分區表中無法使用外鍵約束。
(5)、MySQL的分區適用于一個表的所有數據和索引,不能只對表數據分區而不對索引分區,也不能只對索引分區而不對表分區,也不能只對表的一部分數據分區。
分區類型
目前MySQL支持一下幾種類型的分區,RANGE分區,LIST分區,HASH分區,KEY分區。如果表存在主鍵或者唯一索引時,分區列必須是唯一索引的一個組成部分。實戰十有八九都是用RANGE分區。
RANGE分區
RANGE分區是實戰最常用的一種分區類型,行數據基于屬于一個給定的連續區間的列值被放入分區。但是記住,當插入的數據不在一個分區中定義的值的時候,會拋異常。
RANGE分區主要用于日期列的分區,比如交易表啊,銷售表啊等。可以根據年月來存放數據。如果你分區走的唯一索引中date類型的數據,那么注意了,優化器只能對YEAR(),TO_DAYS(),TO_SECONDS(),UNIX_TIMESTAMP()這類函數進行優化選擇。實戰中可以用int類型,那么只用存yyyyMM就好了。也不用關心函數了。
CREATE?table?`m_test_db`.`Order`?( ????`id`?INT?NOT?NULL?AUTO_INCREMENT, ????`partition_key`?INT?NOT?NULL, ????`amt`?DECIMAL(5)?NULL, ????PRIMARY?KEY?(`id`?,?`partition_key`) )?PARTITION?BY?RANGE?(partition_key)?PARTITIONS?5?( PARTITION?part0?VALUES?less?THAN?(201901)?,? PARTITION?part1?VALUES?LESS?THAN?(201902)?,? PARTITION?part2?VALUES?LESS?THAN?(201903)?,? PARTITION?part3?VALUES?LESS?THAN?(201904)?,? PARTITION?part4?VALUES?LESS?THAN?(201905));
這時候我們先插入一些數據
INSERT?INTO?`m_test_db`.`Order`?(`id`,?`partition_key`,?`amt`)?VALUES?('1',?'201901',?'1000'); INSERT?INTO?`m_test_db`.`Order`?(`id`,?`partition_key`,?`amt`)?VALUES?('2',?'201902',?'800'); INSERT?INTO?`m_test_db`.`Order`?(`id`,?`partition_key`,?`amt`)?VALUES?('3',?'201903',?'1200');
現在我們查詢一下,通過EXPLAIN PARTITION命令發現SQL優化器只需搜對應的區,不會搜索所有分區
如果sql語句有問題,那么會走所有區。會很危險。所以分區表后,select語句必須走分區鍵。
?
以下3種不是太常用,就一筆帶過了。
LIST分區
LIST分區和RANGE分區很相似,只是分區列的值是離散的,不是連續的。LIST分區使用VALUES IN,因為每個分區的值是離散的,因此只能定義值。
HASH分區
說到哈希,那么目的很明顯了,將數據均勻的分布到預先定義的各個分區中,保證每個分區的數量大致相同。
KEY分區
KEY分區和HASH分區相似,不同之處在于HASH分區使用用戶定義的函數進行分區,KEY分區使用數據庫提供的函數進行分區。
分區和性能
一項技術,不是用了就一定帶來益處。比如顯式鎖功能比內置鎖強大,你沒玩好可能導致很不好的情況。分區也是一樣,不是啟動了分區數據庫就會運行的更快,分區可能會給某些sql語句性能提高,但是分區主要用于數據庫高可用性的管理。
數據庫應用分為2類,一類是OLTP(在線事務處理),一類是OLAP(在線分析處理)。對于OLAP應用分區的確可以很好的提高查詢性能,因為一般分析都需要返回大量的數據,如果按時間分區,比如一個月用戶行為等數據,則只需掃描響應的分區即可。在OLTP應用中,分區更加要小心,通常不會獲取一張大表的10%的數據,大部分是通過索引返回幾條數據即可。
比如一張表1000w數據量,如果一句select語句走輔助索引,但是沒有走分區鍵。那么結果會很尷尬。如果1000w的B+樹的高度是3,現在有10個分區。那么不是要(3+3)*10次的邏輯IO?(3次聚集索引,3次輔助索引,10個分區)。所以在OLTP應用中請小心使用分區表。
在日常開發中,如果想查看sql語句的分區查詢結果可以使用explain partitions + select sql來獲取,partitions標識走了哪幾個分區。
mysql>?explain?partitions?select?*?from?TxnList?where?startTime>'2016-08-25?00:00:00'?and?startTime<p>注:</p><p><strong>1.MySQL Workbench下添加分區的截圖</strong></p><p><img src="https://img.php.cn/upload/article/000/000/024/71698832370873cec5e2ebd719f4facf-3.png" alt="" style="max-width:90%" style="max-width:90%" loading="lazy"></p><p><strong>2.?Table has no partition for value 12</strong></p><p>在12月的某一天,我查看了生產的日志文件,忽然發現系統一直在報錯:Table has no partition for value 12。仔細檢查分區sql發現<span style="color: rgba(255, 102, 0, 1)">分區的時候用的是less than</span></p><p><img src="https://img.php.cn/upload/article/000/000/024/ca3d4553413ca47b5c981c86108ab568-4.png" alt="" loading="lazy"></p><p>也就是說我在注釋1截圖里面的分區是不包括12月的區的。執行以下命令增加分區:</p><pre class="brush:php;toolbar:false">ALTER TABLE table_name ADD PARTITION (PARTITION p_12 VALUES LESS THAN (13));
如果沒有進行適當的處理,將會報錯。所以在進行 RANGE 分區時,要思考這種情況。一般情況下,就時在最后添加一個 MAXVALUE 分區,如下:
PARTITION p_max VALUES LESS THAN MAXVALUE
【相關推薦:mysql視頻教程】