日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

MySQL分区:range(范围)list(in)columns(多字段)hash(散列)key(非数值型的hash)复合(hash key)

發(fā)布時(shí)間:2024/9/19 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL分区:range(范围)list(in)columns(多字段)hash(散列)key(非数值型的hash)复合(hash key) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.了解

分區(qū)是把一個(gè)表分成若干個(gè)部分,就是分區(qū),分而化之,表明上還是一張表,內(nèi)容存放在不同的文件了;

數(shù)據(jù)存放在不同的分區(qū)的依據(jù)就是分區(qū)鍵;

3.優(yōu)勢:存儲(chǔ)量大 查詢快 查詢大 方便刪除?

存儲(chǔ)量:和單個(gè)磁盤或者文件系統(tǒng)分區(qū)相比,可以存儲(chǔ)更多數(shù)據(jù);

優(yōu)化查詢:在where子句中包含分區(qū)條件時(shí),可以只掃描必要的一個(gè)或者多個(gè)分區(qū)來提高查詢效率;同時(shí)在涉及sum()和count()這類聚合函數(shù)的查詢時(shí),可以容易的在每個(gè)分區(qū)上并行處理,最終只需要匯總所有分區(qū)得到的結(jié)果

方便刪除:對于已經(jīng)過期或者不需要保存的數(shù)據(jù),可以通過刪除與這些數(shù)據(jù)有關(guān)的分區(qū)來快速刪除數(shù)據(jù)

查詢吞吐量:跨多個(gè)磁盤來分散數(shù)據(jù)查詢,以獲得更大的查詢吞吐量

4.準(zhǔn)備

建表填500w數(shù)據(jù)

CREATE TABLE `tbl_user_no_part` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(255) DEFAULT NULL,`email` varchar(20) DEFAULT NULL,`age` tinyint(4) DEFAULT NULL,`type` int(11) DEFAULT NULL,`create_time` datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;-- 修改mysql默認(rèn)的結(jié)束符號(hào),默認(rèn)是分號(hào);但是在函數(shù)和存儲(chǔ)過程中會(huì)使用到分號(hào)導(dǎo)致解析不正確 delimiter $$ -- 隨機(jī)生成一個(gè)指定長度的字符串 create function rand_string(n int) returns varchar(255) begin # 定義三個(gè)變量declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';declare return_str varchar(255) default '';declare i int default 0;while i < n do set return_str = concat(return_str, substring(chars_str, floor(1+rand()*52), 1));set i = i + 1;end while;return return_str; end $$-- 創(chuàng)建插入的存儲(chǔ)過程 create procedure insert_user(in start int(10), in max_num int(10)) begindeclare i int default 0; set autocommit = 0; repeatset i = i + 1;insert into tbl_user_no_part values ((start+i) ,rand_string(8), concat(rand_string(6), '@random.com'), 1+FLOOR(RAND()*100), 3, now());until i = max_numend repeat;commit; end $$-- 將命令結(jié)束符修改回來 delimiter ;-- 調(diào)用存儲(chǔ)過程,插入500萬數(shù)據(jù),需要等待一會(huì)時(shí)間,等待執(zhí)行完成 call insert_user(100001,5000000);select count(*) from tbl_user_no_part;

5.查看版本可行性

-- 查看mysql版本 select version();-- 查看分區(qū)插件是否激活 partition active show plugins;對于低版本的MySQL,如果InnoDB引擎要想分區(qū)成功,需要在my.conf中設(shè)置innodb_file_per_table=1 設(shè)置成獨(dú)立表空間 獨(dú)立表空間:每張表都有對應(yīng)的.ibd文件 innodb_file_per_table=1

6.range分區(qū):分區(qū)鍵是范圍 范圍分配

6.1定義

-- 語法 create table <table> ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 partition by range (分區(qū)字段) (partition <分區(qū)名稱> values less than (Value),partition <分區(qū)名稱> values less than (Value),...partition <分區(qū)名稱> values less than maxvalue );range:表示按范圍分區(qū) 分區(qū)字段:表示要按照哪個(gè)字段進(jìn)行分區(qū),可以是一個(gè)字段名,也可以是對某個(gè)字段進(jìn)行 表達(dá)式運(yùn)算如year(create_time),使用range最終的值必須是數(shù)字 分區(qū)名稱: 要保證不同,也可以采用 p0、p1、p2 這樣的分區(qū)名稱, less than : 表示小于 Value : 表示要小于某個(gè)具體的值,如 less than (10) 那么分區(qū)字段的值小于10的 都會(huì)被分到這個(gè)分區(qū) maxvalue: 表示一個(gè)最大的值注意:range 對應(yīng)的分區(qū)鍵值必須是數(shù)字值,可以使用range columns(分區(qū)字段) 對非int型做分區(qū), 如字符串,對于日期類型的可以使用year()、to_days()、to_seconds()等函數(shù) create table emp_date(id int not null,separated date not null default '9999-12-31' ) partition by range columns(separated) (partiontion p0 values less than ('1990-01-01'),partiontion p0 values less than ('2001-01-01'),partiontion p0 values less than ('2018-01-01') );分區(qū)可以在創(chuàng)建表的時(shí)候進(jìn)行分區(qū),也可以在創(chuàng)建表之后進(jìn)行分區(qū) alter table <table> partition by RANGE(id) (PARTITION p0 VALUES LESS THAN (1000000),PARTITION p1 VALUES LESS THAN (2000000),PARTITION p2 VALUES LESS THAN (3000000),PARTITION p3 VALUES LESS THAN (4000000),PARTITION p4 VALUES LESS THAN MAXVALUE );

6.2案例

-- 創(chuàng)建分區(qū)表 CREATE TABLE `tbl_user_part` (`id` int(11) NOT NULL ,`username` varchar(255) DEFAULT NULL,`email` varchar(20) DEFAULT NULL,`age` tinyint(4) DEFAULT NULL,`type` int(11) DEFAULT NULL,`create_time` datetime DEFAULT CURRENT_TIMESTAMPPRIMARY KEY (`id`,`age`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 PARTITION BY RANGE (age) (PARTITION p0 VALUES LESS THAN (20),PARTITION p1 VALUES LESS THAN (40),PARTITION p2 VALUES LESS THAN (60),PARTITION p3 VALUES LESS THAN (80),PARTITION p4 VALUES LESS THAN MAXVALUE );

?6.3.錯(cuò)誤

A PRIMARY KEY must include all columns in the table’s partitioning function。

意思是說分區(qū)的字段必須是要包含在主鍵當(dāng)中。 可以使用PRIMARY KEY (id,xxx)來將多個(gè)字段作為主鍵。

在做分區(qū)表時(shí),選擇分區(qū)的依據(jù)字段時(shí)要謹(jǐn)慎,需要仔細(xì)斟酌這個(gè)字段拿來做為分區(qū)依據(jù)是否合適,

這個(gè)字段加入到主鍵中做為復(fù)合主鍵是否適合。

6.4.對比

7.list :使用in 固定分配

-- 語法 create table <table> (// 字段 ) ENGINE=數(shù)據(jù)庫引擎 DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 partition by LIST (分區(qū)字段或者基于該字段的返回的整數(shù)值的表達(dá)式) (partition <分區(qū)名稱> values IN (Value1,Value2, Value3),...partition <分區(qū)名稱> values IN (Value4, Value5), );

8.columns

columns分區(qū)分為 range columns 和 list columns 兩種

支持整數(shù)(tinyint到bigint,不支持decimal 和float)、日期(date、datetime)、字符串(char、varchar、binary、varbinary)三類

columns分區(qū)支持一個(gè)或者多個(gè)字段作為分區(qū)鍵,不支持表達(dá)式作為分區(qū)鍵,這點(diǎn)區(qū)別于range 和 list 分區(qū)。

多列排序,先根據(jù)a字段排序再根據(jù)b字段排序,根據(jù)排序結(jié)果來分區(qū)存放數(shù)據(jù)

create talbe rc3 (a int,b int ) partition by range columns(a, b) (partition p01 values less than (0, 10),partition p02 values less than (10, 10),partition p03 values less than (10, 20),partition p04 values less than (10, 35),partition p05 values less than (10, maxvalue),partition p06 values less than (maxvalue, maxvalue), ); insert into rc3(a, b) values(1, 10); select (1, 10) < (10, 10) from dual; -- 根據(jù)結(jié)果存放到p02分區(qū)上了 1小于10 10等于10 在02規(guī)定的范圍內(nèi) selectpartition_name,partition_expression,partition_description,table_rows from information_schema.partitions where table_schema = schema() and table_name = 'rc3';

9.hash:散列函數(shù)

9.1定義

分區(qū)鍵應(yīng)用一個(gè)散列函數(shù),以此確定數(shù)據(jù)應(yīng)當(dāng)放在N個(gè)分區(qū)中的哪個(gè)分區(qū)

mysql支持兩種hash分區(qū):常規(guī)hash分區(qū)和線性hash分區(qū)

  • 常規(guī)hash分區(qū)使用的是取模算法,對應(yīng)一個(gè)表達(dá)式expr是可以計(jì)算出它被保存到哪個(gè)分區(qū)中,N = MOD(expr, num)
  • 線性hash分區(qū)使用的是一個(gè)線性的2的冪運(yùn)算法則。

對指定的字段(整型字段)進(jìn)行哈希,將記錄平均的分配到分區(qū)中,使得所有分區(qū)的數(shù)據(jù)比較平均。 hash分區(qū)只需要指定要分區(qū)的字段和要分成幾個(gè)分區(qū),
expr是一個(gè)字段值或者基于某列值云散返回的一個(gè)整數(shù),

expr可以是mysql中有效的任何函數(shù)或者其它表達(dá)式,只要它們返回一個(gè)即非常熟也非隨機(jī)數(shù)的整數(shù)。num 表示分區(qū)數(shù)量

-- HASH create table <table> (// 字段 ) ENGINE=數(shù)據(jù)庫引擎 DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 PARTITION BY HASH(expr) PARTITIONS <num>;

9.2常規(guī)hash問題:新增的話 會(huì)導(dǎo)致重新計(jì)算

常規(guī)hash分區(qū)方式看上去挺不錯(cuò)的,通過取模的方式來數(shù)據(jù)盡可能平均分布在每個(gè)分區(qū),讓每個(gè)分區(qū)管理的數(shù)據(jù)都減少,提高查詢效率,可是當(dāng)我們要增加分區(qū)時(shí)或者合并分區(qū),問題就來了,假設(shè)原來是5個(gè)常規(guī)hash分區(qū),現(xiàn)在需要增加一個(gè)常規(guī)分區(qū),原來的取模算法是MOD(expr, 5), 根據(jù)余數(shù)0~4分布在5個(gè)分區(qū)中,現(xiàn)在新增一個(gè)分區(qū)后,取模算法變成MOD(expr, 6),根據(jù)余數(shù)0~6分區(qū)在6個(gè)分區(qū)中,原來5個(gè)分區(qū)的數(shù)據(jù)大部分都需要通過重新計(jì)算進(jìn)行重新分區(qū)。

9.3?線性hash分區(qū)

常規(guī)hash分區(qū)在管理上帶來了的代價(jià)太大,不適合需要靈活變動(dòng)分區(qū)的需求。為了降低分區(qū)管理上的代價(jià),mysql提供了線性hash分區(qū),分區(qū)函數(shù)是一個(gè)線性的2的冪的運(yùn)算法則。同樣線性hash分區(qū)的記錄被存在那個(gè)分區(qū)也是能被計(jì)算出來的。線性hash分區(qū)的優(yōu)點(diǎn)是在分區(qū)維護(hù)(增加、刪除、合并、拆分分區(qū))時(shí),mysql能夠處理的更加迅速,缺點(diǎn)是:對比常規(guī)hash分區(qū),線性hash各個(gè)分區(qū)之間數(shù)據(jù)的分布不太均衡。

-- LINEAR HASH create table <table> (// 字段 ) ENGINE=數(shù)據(jù)庫引擎 DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 PARTITION BY LINEAR HASH(expr) PARTITIONS <num>;

10.key

照key進(jìn)行分區(qū)非常類似于按照hash進(jìn)行分區(qū)?分區(qū)的字段可以是非int類型,如字符串、日期等類型

partition by key(expr) partitions num;-- 不指定默認(rèn)首選主鍵作為分區(qū)鍵,在沒有主鍵的情況下會(huì)選擇非空唯一鍵作為分區(qū)鍵 partition by key() partitions num;-- linear key partition by linear key(expr)create table <table> (// 字段 ) ENGINE=數(shù)據(jù)庫引擎 DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 PARTITION BY HASH(分區(qū)字段名) PARTITIONS <count>;

11.復(fù)合分區(qū)

是分區(qū)表中對每個(gè)分區(qū)的再次分割,支持對range和list進(jìn)行父分區(qū),復(fù)合分區(qū)即可以使用hash分區(qū)也可以使用key分區(qū)進(jìn)行子分區(qū)。

復(fù)合分區(qū)適用于保存非常大量的數(shù)據(jù)記錄。

-- 根據(jù)年進(jìn)行分區(qū) -- 再根據(jù)天數(shù)分區(qū) -- 3個(gè)range分區(qū)(p0,p1,p2)又被進(jìn)一步分成2個(gè)子分區(qū),實(shí)際上整個(gè)分區(qū)被分成了 3 x 2 = 6個(gè)分區(qū) create table ts (id int, purchased date ) partition by range(year(purchased)) subpartition by hash(to_days(purchased)) subpartitions 2 (partition p0 values less than (1990),partition p0 values less than (2000),partition p0 values less than maxvalue );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 '來源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) );

12.管理分區(qū)

mysql提供了添加、刪除、重定義、合并、拆分分區(qū)的命令,這些操作都可以通過alter table 命令來實(shí)現(xiàn)

-- 刪除list或者range分區(qū)(同時(shí)刪除分區(qū)對應(yīng)的數(shù)據(jù)) alter table <table> drop partition <分區(qū)名稱>;-- 新增分區(qū) -- range添加新分區(qū) alter table <table> add partition(partition p4 values less than MAXVALUE);-- list添加新分區(qū) alter table <table> add partition(partition p4 values in (25,26,28));-- hash重新分區(qū) alter table <table> add partition partitions 4;-- key重新分區(qū) alter table <table> add partition partitions 4;-- 子分區(qū)添加新分區(qū),雖然我沒有指定子分區(qū),但是系統(tǒng)會(huì)給子分區(qū)命名的 alter table <table> add partition(partition p3 values less than MAXVALUE);-- range重新分區(qū) ALTER TABLE user REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES LESS THAN MAXVALUE);-- list重新分區(qū) ALTER TABLE <table> REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES in (1,2,3,4,5));

?

總結(jié)

以上是生活随笔為你收集整理的MySQL分区:range(范围)list(in)columns(多字段)hash(散列)key(非数值型的hash)复合(hash key)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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