日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql 分区表优化_Sql优化之Mysql表分区

發(fā)布時(shí)間:2025/3/21 数据库 76 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 分区表优化_Sql优化之Mysql表分区 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一??分區(qū)表適用于以下場(chǎng)景

1:表非常大以至于無(wú)法全部放在內(nèi)存中,或者只在標(biāo)的最后部分有熱點(diǎn)數(shù)據(jù),其他均是歷史數(shù)據(jù)

2:分區(qū)表的數(shù)據(jù)更容易維護(hù)。例如想批量刪除大量數(shù)據(jù)可以使用清除整個(gè)分區(qū)的方式。另外還可以對(duì)一個(gè)獨(dú)立分區(qū)進(jìn)行優(yōu)化、檢查、修復(fù)等操作。

3:分區(qū)表的數(shù)據(jù)可以分布在不同的物理設(shè)備上,從而高效的利用多個(gè)硬件設(shè)備

4:可以使用分區(qū)表來(lái)避免某些特殊的瓶頸。例如InnoDB的單個(gè)索引的互斥訪問(wèn)、ext3文件系統(tǒng)的inode鎖競(jìng)爭(zhēng)等。

5:如果需要,還可以備份和恢復(fù)獨(dú)立的分區(qū),這在非常大的數(shù)據(jù)集的場(chǎng)景下效果非常好。

二? 分區(qū)原理以及限制

mysql數(shù)據(jù)庫(kù)中的數(shù)據(jù)是以文件的形勢(shì)存在磁盤(pán)上的,默認(rèn)放在/mysql/data下面(可以通過(guò)my.cnf中的datadir來(lái)查看),一張表主要對(duì)應(yīng)著三個(gè)文件,一個(gè)是frm存放表結(jié)構(gòu)的,一個(gè)是myd存放表數(shù)據(jù)的,

一個(gè)是myi存表索引的。如果一張表的數(shù)據(jù)量太大的話,那么myd,myi就會(huì)變的很大,查找數(shù)據(jù)就會(huì)變的很慢,這個(gè)時(shí)候我們可以利用mysql的分區(qū)功能,

在物理上將這一張表對(duì)應(yīng)的三個(gè)文件,分割成許多個(gè)小塊,這樣呢,我們查找一條數(shù)據(jù)時(shí),就不用全部查找了,只要知道這條數(shù)據(jù)在哪一塊,然后在那一塊找就行了。

如果表的數(shù)據(jù)太大,可能一個(gè)磁盤(pán)放不下,這個(gè)時(shí)候,我們可以把數(shù)據(jù)分配到不同的磁盤(pán)里面去。

分區(qū)表的限制

分區(qū)表的原理

SELECT 查詢(xún):當(dāng)查詢(xún)一個(gè)分區(qū)表的時(shí)候,分區(qū)層先打開(kāi)并鎖住所有底層表,優(yōu)化器先判斷是否可以過(guò)濾部分分區(qū),然后再調(diào)用對(duì)應(yīng)的存儲(chǔ)引擎接口訪問(wèn)各個(gè)分區(qū)的數(shù)據(jù);

INSERT操作:當(dāng)寫(xiě)入一條數(shù)據(jù)時(shí),分區(qū)層先打開(kāi)并鎖住所有的底層表,然后確定那個(gè)分區(qū)接收這條數(shù)據(jù),然后再將記錄寫(xiě)入對(duì)應(yīng)的底層表;

DELETE操作:當(dāng)刪除一條記錄時(shí),分區(qū)層現(xiàn)代開(kāi)并鎖住所有的底層表,然后確定數(shù)據(jù)對(duì)應(yīng)的分區(qū),最后對(duì)相應(yīng)底層進(jìn)行刪除操作;

UPDATE操作:當(dāng)更新一條記錄時(shí),分區(qū)層先打開(kāi)并鎖住所有的底層表,MYSQL先確定需要更新的記錄在哪個(gè)分區(qū),然后取出數(shù)據(jù)并更新,在判斷更新后的數(shù)據(jù)應(yīng)該放在哪個(gè)分區(qū),最后對(duì)底層表進(jìn)行寫(xiě)入操作,并對(duì)原數(shù)據(jù)所在的底層表進(jìn)行刪除操作。

當(dāng)然其中有些操作是支持過(guò)濾的。例如當(dāng)刪除一條記錄時(shí),MYSQL 需要先找到這條記錄,如果where條件恰好和分區(qū)表達(dá)式匹配,就可以將所有不包含這條記錄的分區(qū)都過(guò)濾掉。同樣的操作對(duì)于update同樣有效。如果是insert操作,其本身就是只命中一個(gè)分區(qū) ,其他分區(qū)都會(huì)被過(guò)濾掉。MYSQL先確定這條記錄屬于哪個(gè)分區(qū),再將記錄寫(xiě)入對(duì)應(yīng)的底層分區(qū)表,無(wú)須對(duì)任何其他分區(qū)進(jìn)行操作。(雖然每個(gè)操作都會(huì)“”“先打開(kāi)并鎖住所有的底層表”,但是并不是說(shuō)分區(qū)表在處理過(guò)程中是鎖住全表的,如果存儲(chǔ)引擎能夠自己實(shí)現(xiàn)行級(jí)鎖,例如InnoDB,則會(huì)在分區(qū)層釋放對(duì)應(yīng)表鎖)。

分區(qū)表的類(lèi)型:MYSQL支持多種分區(qū)表

最常見(jiàn)的就是根據(jù)范圍進(jìn)行分區(qū),每個(gè)分區(qū)存儲(chǔ)落在某個(gè)范圍的記錄,分區(qū)表達(dá)式可以是列,也可以是列的表達(dá)式。下面的例子是將每一年的銷(xiāo)售額存放在不同的分區(qū)里。

三? ? 創(chuàng)建分區(qū)操作

RANGE分區(qū):

mysql> CREATE TABLE `operation_log` (

-> `id` int(11) unsigned NOT NULL AUTO_INCREMENT,

-> `cid` mediumint(7) unsigned NOT NULL,

-> `accountid` mediumint(8) NOT NULL DEFAULT '0' ,

-> `flag` tinyint(1) unsigned NOT NULL DEFAULT '0',

-> `addtime` int(11) unsigned NOT NULL,

-> `device` tinyint(1) unsigned NOT NULL DEFAULT '1' ,

-> PRIMARY KEY (`id`,`addtime`),

-> KEY `idx_accountid_addtime` (`accountid`,`addtime`),

-> KEY `idx_accountid_flag` (`accountid`,`flag`),

->) ENGINE=InnoDB AUTO_INCREMENT=50951039 DEFAULT CHARSET=utf8 COMMENT='操作記錄'

->/*!50100 PARTITION BY RANGE (addtime)

->(PARTITION `2013-05` VALUES LESS THAN (1370016000) ENGINE = InnoDB,

-> PARTITION `2013-06` VALUES LESS THAN (1372608000) ENGINE = InnoDB,

-> PARTITION `2013-07` VALUES LESS THAN (1375286400) ENGINE = InnoDB,

-> PARTITION `2013-08` VALUES LESS THAN (1377964800) ENGINE = InnoDB,

-> PARTITION `2013-09` VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;

1 row in set (0.00 sec)

( LESS THAN MAXVALUE考慮到可能的最大值)

list分區(qū)

//這種方式失敗

mysql> CREATE TABLE IF NOT EXISTS `list_part` (

-> `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶(hù)ID',

-> `province_id` int(2) NOT NULL DEFAULT 0 COMMENT '省',

-> `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名稱(chēng)',

-> `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0為男,1為女',

-> PRIMARY KEY (`id`)

-> ) ENGINE=INNODB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1

-> PARTITION BY LIST (province_id) (

-> PARTITION p0 VALUES IN (1,2,3,4,5,6,7,8),

-> PARTITION p1 VALUES IN (9,10,11,12,16,21),

-> PARTITION p2 VALUES IN (13,14,15,19),

-> PARTITION p3 VALUES IN (17,18,20,22,23,24)

-> );

ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

//這種方式成功

mysql> CREATE TABLE IF NOT EXISTS `list_part` (

-> `id` int(11) NOT NULL COMMENT '用戶(hù)ID',

-> `province_id` int(2) NOT NULL DEFAULT 0 COMMENT '省',

-> `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名稱(chēng)',

-> `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0為男,1為女'

-> ) ENGINE=INNODB DEFAULT CHARSET=utf8

-> PARTITION BY LIST (province_id) (

-> PARTITION p0 VALUES IN (1,2,3,4,5,6,7,8),

-> PARTITION p1 VALUES IN (9,10,11,12,16,21),

-> PARTITION p2 VALUES IN (13,14,15,19),

-> PARTITION p3 VALUES IN (17,18,20,22,23,24)

-> );

Query OK, 0 rows affected (0.33 sec)

上面的這個(gè)創(chuàng)建list分區(qū)時(shí),如果有主銉的話,分區(qū)時(shí)主鍵必須在其中,不然就會(huì)報(bào)錯(cuò)。如果我不用主鍵,分區(qū)就創(chuàng)建成功了,一般情況下,一個(gè)張表肯定會(huì)有一個(gè)主鍵,這算是一個(gè)分區(qū)的局限性

hash分區(qū)

mysql> CREATE TABLE IF NOT EXISTS `hash_part` (

-> `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '評(píng)論ID',

-> `comment` varchar(1000) NOT NULL DEFAULT '' COMMENT '評(píng)論',

-> `ip` varchar(25) NOT NULL DEFAULT '' COMMENT '來(lái)源IP',

-> PRIMARY KEY (`id`)

-> ) ENGINE=INNODB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1

-> PARTITION BY HASH(id)

-> PARTITIONS 3;

Query OK, 0 rows affected (0.06 sec)

key分區(qū)

mysql> CREATE TABLE IF NOT EXISTS `key_part` (

-> `news_id` int(11) NOT NULL COMMENT '新聞ID',

-> `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新聞內(nèi)容',

-> `u_id` varchar(25) NOT NULL DEFAULT '' COMMENT '來(lái)源IP',

-> `create_time` DATE NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '時(shí)間'

-> ) ENGINE=INNODB DEFAULT CHARSET=utf8

-> PARTITION BY LINEAR HASH(YEAR(create_time))

-> PARTITIONS 3;

Query OK, 0 rows affected (0.07 sec)

增加子分區(qū)操作

子分區(qū)是分區(qū)表中每個(gè)分區(qū)的再次分割,子分區(qū)既可以使用HASH希分區(qū),也可以使用KEY分區(qū)。這 也被稱(chēng)為復(fù)合分區(qū)(composite partitioning)

1. 如果一個(gè)分區(qū)中創(chuàng)建了子分區(qū),其他分區(qū)也要有子分區(qū)

2. 如果創(chuàng)建了了分區(qū),每個(gè)分區(qū)中的子分區(qū)數(shù)必有相同

3. 同一分區(qū)內(nèi)的子分區(qū),名字不相同,不同分區(qū)內(nèi)的子分區(qū)名子可以相同(5.1.50不適用)

1

2

3

4

5

6

7

8

9

10

11

12

13

mysql> CREATE TABLE IF NOT EXISTS `sub_part` (

-> `news_id` int(11) NOT NULL COMMENT '新聞ID',

-> `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新聞內(nèi)容',

-> `u_id` int(11) NOT NULL DEFAULT 0s COMMENT '來(lái)源IP',

-> `create_time` DATE NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '時(shí)間'

-> ) ENGINE=INNODB DEFAULT CHARSET=utf8

-> PARTITION BY RANGE(YEAR(create_time))

-> SUBPARTITION BY HASH(TO_DAYS(create_time))(

-> PARTITION p0 VALUES LESS THAN (1990)(SUBPARTITION s0,SUBPARTITION s1,SUBPARTITION s2),

-> PARTITION p1 VALUES LESS THAN (2000)(SUBPARTITION s3,SUBPARTITION s4,SUBPARTITION good),

-> PARTITION p2 VALUES LESS THAN MAXVALUE(SUBPARTITION tank0,SUBPARTITION tank1,SUBPARTITION tank3)

-> );

Query OK, 0 rows affected (0.07 sec)

分區(qū)管理

增加分區(qū)操作(針對(duì)設(shè)置MAXVALUE)

range添加分區(qū)

1

2

3

mysql>alter table operation_log add partition(partition `2013-10` values less than (1383235200)); --->適用于沒(méi)有設(shè)置MAXVALUE的分區(qū)添加

ERROR 1481 (HY000):MAXVALUE can only be used in last partition definition

mysql>alter table operation_log REORGANIZE partition `2013-09` into (partition `2013-09` values less than (1380556800),partition `2013-10` values less than (1383235200),partition `2013-11` values less than maxvalue);

list添加分區(qū)

1

2

3

mysql> alter table list_part add partition(partition p4 values in (25,26,28));

Query OK, 0 rows affected (0.01 sec)

Records: 0 Duplicates: 0 Warnings: 0

hash重新分區(qū)

1

2

3

mysql> alter table list_part add partition(partition p4 values in (25,26,28));

Query OK, 0 rows affected (0.01 sec)

Records: 0 Duplicates: 0 Warnings: 0

key重新分區(qū)

1

2

3

mysql> alter table key_part add partition partitions 4;

Query OK, 1 row affected (0.06 sec)//有數(shù)據(jù)也會(huì)被重新分配

Records: 1 Duplicates: 0 Warnings: 0

子分區(qū)添加新分區(qū),雖然我沒(méi)有指定子分區(qū),但是系統(tǒng)會(huì)給子分區(qū)命名的

1

2

3

mysql> alter table sub1_part add partition(partition p3 values less than MAXVALUE);

Query OK, 0 rows affected (0.02 sec)

Records: 0 Duplicates: 0 Warnings: 0

刪除分區(qū)操作

alter table user drop partition2013-05;

分區(qū)表其他操作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

重建分區(qū)(官方:與先drop所有記錄然后reinsert是一樣的效果;用于整理表碎片)

alter table operation_log rebuild partition `2014-01`;

重建多個(gè)分區(qū)

alter table operation_log rebuild partition `2014-01`,`2014-02`;

過(guò)程如下:

pro

優(yōu)化分區(qū)(如果刪除了一個(gè)分區(qū)的大量記錄或者對(duì)一個(gè)分區(qū)的varchar blob text數(shù)據(jù)類(lèi)型的字段做了許多更新,此時(shí)可以對(duì)分區(qū)進(jìn)行優(yōu)化以回收未使用的空間和整理分區(qū)數(shù)據(jù)文件)

alter table operation_log optimize partition `2014-01`;

優(yōu)化的操作相當(dāng)于check partition,analyze partition 和repair patition

分析分區(qū)

alter table operation_log analyze partition `2014-01`;

修復(fù)分區(qū)

alter table operation_log repair partition `2014-01`;

檢查分區(qū)

alter table operation_log check partition `2014-01`;

總結(jié)

以上是生活随笔為你收集整理的mysql 分区表优化_Sql优化之Mysql表分区的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。