傳統(tǒng)的分庫分表
傳統(tǒng)的分庫分表都是通過應用層邏輯實現(xiàn)的,對于數(shù)據(jù)庫層面來說,都是普通的表和庫。
分庫
分庫的原因
首先,在單臺數(shù)據(jù)庫服務(wù)器性能足夠的情況下,分庫對于數(shù)據(jù)庫性能是沒有影響的。在數(shù)據(jù)庫存儲上,database只起到一個namespace的作用。database中的表文件存儲在一個以database名命名的文件夾中。比如下面的employees數(shù)據(jù)庫:
mysql> show tables in employees;
+---------------------+
| Tables_in_employees |
+---------------------+
| departments |
| dept_emp |
| dept_manager |
| employees |
| salaries |
| titles |
+---------------------+
在操作系統(tǒng)中看是這樣的:
# haitian at haitian-coder.local in /usr/local/var/mysql/employees on git:master ● [21:19:47]
→ ls
db.opt dept_emp.frm dept_manager.ibd salaries.frm titles.ibd
departments.frm dept_emp.ibd employees.frm salaries.ibd
departments.ibd dept_manager.frm employees.ibd titles.frm
database不是文件,只起到namespace的作用,所以MySQL對database大小當然也是沒有限制的,而且對里面的表數(shù)量也沒有限制。
C.10.2 Limits on Number of Databases and Tables
MySQL has no limit on the number of databases. The underlying file
system may have a limit on the number of directories.
MySQL has no limit on the number of tables. The underlying file system
may have a limit on the number of files that represent tables.
Individual storage engines may impose engine-specific constraints.
InnoDB permits up to 4 billion tables.
所以,為什么要分庫呢?
答案是為了解決單臺服務(wù)器的性能問題,當單臺數(shù)據(jù)庫服務(wù)器無法支撐當前的數(shù)據(jù)量時,就需要根據(jù)業(yè)務(wù)邏輯緊密程度把表分成幾撮,分別放在不同的數(shù)據(jù)庫服務(wù)器中以降低單臺服務(wù)器的負載。
分庫一般考慮的是垂直切分,除非在垂直切分后,數(shù)據(jù)量仍然多到單臺服務(wù)器無法負載,才繼續(xù)水平切分。
比如一個論壇系統(tǒng)的數(shù)據(jù)庫因當前服務(wù)器性能無法滿足需要進行分庫。先垂直切分,按業(yè)務(wù)邏輯把用戶相關(guān)數(shù)據(jù)表比如用戶信息、積分、用戶間私信等放入user數(shù)據(jù)庫;論壇相關(guān)數(shù)據(jù)表比如板塊,帖子,回復等放入forum數(shù)據(jù)庫,兩個數(shù)據(jù)庫放在不同服務(wù)器上。
拆分后表往往不可能完全無關(guān)聯(lián),比如帖子中的發(fā)帖人、回復人這些信息都在user數(shù)據(jù)庫中。未拆分前可能一次聯(lián)表查詢就能獲取當前帖子的回復、發(fā)帖人、回復人等所有信息,拆分后因為跨數(shù)據(jù)庫無法聯(lián)表查詢,只能多次查詢獲得最終數(shù)據(jù)。
所以總結(jié)起來,分庫的目的是降低單臺服務(wù)器負載,切分原則是根據(jù)業(yè)務(wù)緊密程度拆分,缺點是跨數(shù)據(jù)庫無法聯(lián)表查詢。
分表
分表的原因
當數(shù)據(jù)量超大的時候,B-Tree索引就無法起作用了。除非是索引覆蓋查詢,否則數(shù)據(jù)庫服務(wù)器需要根據(jù)索引掃描的結(jié)果回表,查詢所有符合條件的記錄,如果數(shù)據(jù)量巨大,這將產(chǎn)生大量隨機I/O,隨之,數(shù)據(jù)庫的響應時間將大到不可接受的程度。另外,索引維護(磁盤空間、I/O操作)的代價也非常高。
垂直分表
原因:
1.根據(jù)MySQL索引實現(xiàn)原理及相關(guān)優(yōu)化策略的內(nèi)容我們知道Innodb主索引葉子節(jié)點存儲著當前行的所有信息,所以減少字段可使內(nèi)存加載更多行數(shù)據(jù),有利于查詢。
2.受限于操作系統(tǒng)中的文件大小限制。
切分原則:
把不常用或業(yè)務(wù)邏輯不緊密或存儲內(nèi)容比較多的字段分到新的表中可使表存儲更多數(shù)據(jù)。。
水平分表
原因:
1.隨著數(shù)據(jù)量的增大,table行數(shù)巨大,查詢的效率越來越低。
2.同樣受限于操作系統(tǒng)中的文件大小限制,數(shù)據(jù)量不能無限增加,當?shù)竭_一定容量時,需要水平切分以降低單表(文件)的大小。
切分原則: 增量區(qū)間或散列或其他業(yè)務(wù)邏輯。
使用哪種切分方法要根據(jù)實際業(yè)務(wù)邏輯判斷。
比如對表的訪問多是近期產(chǎn)生的新數(shù)據(jù),歷史數(shù)據(jù)訪問較少,可以考慮根據(jù)時間增量把數(shù)據(jù)按照一定時間段(比如每年)切分。
如果對表的訪問較均勻,沒有明顯的熱點區(qū)域,則可以考慮用范圍(比如每500w一個表)或普通Hash或一致性Hash來切分。
全局主鍵問題:
原本依賴數(shù)據(jù)庫生成主鍵(比如自增)的表在拆分后需要自己實現(xiàn)主鍵的生成,因為一般拆分規(guī)則是建立在主鍵上的,所以在插入新數(shù)據(jù)時需要確定主鍵后才能找到存儲的表。
實際應用中也已經(jīng)有了比較成熟的方案。比如對于自增列做主鍵的表,flickr的全局主鍵生成方案很好的解決了性能和單點問題,具體實現(xiàn)原理可以參考這個帖子。除此之外,還有類似于uuid的全局主鍵生成方案,比如達達參考的Instagram的ID生成器。
一致性Hash:
使用一致性Hash切分比普通的Hash切分可擴展性更強,可以實現(xiàn)拆分表的添加和刪除。一致性Hash的具體原理可以參考這個帖子,如果拆分后的表存儲在不同服務(wù)器節(jié)點上,可以跟帖子一樣對節(jié)點名或ip取Hash;如果拆分后的表存在一個服務(wù)器中則可對拆分后的表名取Hash。
MySQL的分區(qū)表
上面介紹的傳統(tǒng)的分庫分表都是在應用層實現(xiàn),拆分后都要對原有系統(tǒng)進行很大的調(diào)整以適應新拆分后的庫或表,比如實現(xiàn)一個SQL中間件、原本的聯(lián)表查詢改成兩次查詢、實現(xiàn)一個全局主鍵生成器等等。
而下面介紹的MySQL分區(qū)表是在數(shù)據(jù)庫層面,MySQL自己實現(xiàn)的分表功能,在很大程度上簡化了分表的難度。
介紹
對用戶來說,分區(qū)表是一個獨立的邏輯表,但是底層由多個物理子表實現(xiàn)。
也就是說,對于原表分區(qū)后,對于應用層來說可以不做變化,我們無需改變原有的SQL語句,相當于MySQL幫我們實現(xiàn)了傳統(tǒng)分表后的SQL中間件,當然,MySQL的分區(qū)表的實現(xiàn)要復雜很多。
另外,在創(chuàng)建分區(qū)時可以指定分區(qū)的索引文件和數(shù)據(jù)文件的存儲位置,所以可以把數(shù)據(jù)表的數(shù)據(jù)分布在不同的物理設(shè)備上,從而高效地利用多個硬件設(shè)備。
一些限制:
1.在5.6.7之前的版本,一個表最多有1024個分區(qū);從5.6.7開始,一個表最多可以有8192個分區(qū)。
2.分區(qū)表中無法使用外鍵約束。
3.主表的所有唯一索引列(包括主鍵)都必須包含分區(qū)字段。MySQL官方文檔中寫的是:
All columns used in the partitioning expression for a partitioned
table must be part of every unique key that the table may have.
這句話不是很好理解,需要通過例子才能明白,MySQL官方文檔也為此限制特意做了舉例和解釋。
分區(qū)表的類型
RANGE分區(qū)
根據(jù)范圍分區(qū),范圍應該連續(xù)但是不重疊,使用PARTITION BY RANGE, VALUES LESS THAN關(guān)鍵字。不使用COLUMNS關(guān)鍵字時RANGE括號內(nèi)必須為整數(shù)字段名或返回確定整數(shù)的函數(shù)。
根據(jù)數(shù)值范圍:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
根據(jù)TIMESTAMP范圍:
CREATE TABLE quarterly_report_status (
report_id INT NOT NULL,
report_status VARCHAR(20) NOT NULL,
report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
PARTITION p9 VALUES LESS THAN (MAXVALUE)
);
添加COLUMNS關(guān)鍵字可定義非integer范圍及多列范圍,不過需要注意COLUMNS括號內(nèi)只能是列名,不支持函數(shù);多列范圍時,多列范圍必須呈遞增趨勢:
根據(jù)DATE、DATETIME范圍:
CREATE TABLE members (
firstname VARCHAR(25) NOT NULL,
lastname VARCHAR(25) NOT NULL,
username VARCHAR(16) NOT NULL,
email VARCHAR(35),
joined DATE NOT NULL
)
PARTITION BY RANGE COLUMNS(joined) (
PARTITION p0 VALUES LESS THAN ('1960-01-01'),
PARTITION p1 VALUES LESS THAN ('1970-01-01'),
PARTITION p2 VALUES LESS THAN ('1980-01-01'),
PARTITION p3 VALUES LESS THAN ('1990-01-01'),
PARTITION p4 VALUES LESS THAN MAXVALUE
);
根據(jù)多列范圍:
CREATE TABLE rc3 (
a INT,
b INT
)
PARTITION BY RANGE COLUMNS(a,b) (
PARTITION p0 VALUES LESS THAN (0,10),
PARTITION p1 VALUES LESS THAN (10,20),
PARTITION p2 VALUES LESS THAN (10,30),
PARTITION p3 VALUES LESS THAN (10,35),
PARTITION p4 VALUES LESS THAN (20,40),
PARTITION p5 VALUES LESS THAN (MAXVALUE,MAXVALUE)
);
List分區(qū)
根據(jù)具體數(shù)值分區(qū),每個分區(qū)數(shù)值不重疊,使用PARTITION BY LIST、VALUES IN關(guān)鍵字。跟Range分區(qū)類似,不使用COLUMNS關(guān)鍵字時List括號內(nèi)必須為整數(shù)字段名或返回確定整數(shù)的函數(shù)。
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY LIST(store_id) (
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20),
PARTITION pWest VALUES IN (4,12,13,14,18),
PARTITION pCentral VALUES IN (7,8,15,16)
);
數(shù)值必須被所有分區(qū)覆蓋,否則插入一個不屬于任何一個分區(qū)的數(shù)值會報錯。
mysql> CREATE TABLE h2 (
-> c1 INT,
-> c2 INT
-> )
-> PARTITION BY LIST(c1) (
-> PARTITION p0 VALUES IN (1, 4, 7),
-> PARTITION p1 VALUES IN (2, 5, 8)
-> );
Query OK, 0 rows affected (0.11 sec)
mysql> INSERT INTO h2 VALUES (3, 5);
ERROR 1525 (HY000): Table has no partition for value 3
當插入多條數(shù)據(jù)出錯時,如果表的引擎支持事務(wù)(Innodb),則不會插入任何數(shù)據(jù);如果不支持事務(wù),則出錯前的數(shù)據(jù)會插入,后面的不會執(zhí)行。
可以使用IGNORE關(guān)鍵字忽略出錯的數(shù)據(jù),這樣其他符合條件的數(shù)據(jù)會全部插入不受影響。
mysql> TRUNCATE h2;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM h2;
Empty set (0.00 sec)
mysql> INSERT IGNORE INTO h2 VALUES (2, 5), (6, 10), (7, 5), (3, 1), (1, 9);
Query OK, 3 rows affected (0.00 sec)
Records: 5 Duplicates: 2 Warnings: 0
mysql> SELECT * FROM h2;
+------+------+
| c1 | c2 |
+------+------+
| 7 | 5 |
| 1 | 9 |
| 2 | 5 |
+------+------+
3 rows in set (0.00 sec)
與Range分區(qū)相同,添加COLUMNS關(guān)鍵字可支持非整數(shù)和多列。
Hash分區(qū)
Hash分區(qū)主要用來確保數(shù)據(jù)在預先確定數(shù)目的分區(qū)中平均分布,Hash括號內(nèi)只能是整數(shù)列或返回確定整數(shù)的函數(shù),實際上就是使用返回的整數(shù)對分區(qū)數(shù)取模。
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4;
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;
Hash分區(qū)也存在與傳統(tǒng)Hash分表一樣的問題,可擴展性差。MySQL也提供了一個類似于一致Hash的分區(qū)方法-線性Hash分區(qū),只需要在定義分區(qū)時添加LINEAR關(guān)鍵字,如果對實現(xiàn)原理感興趣,可以查看官方文檔。
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY LINEAR HASH( YEAR(hired) )
PARTITIONS 4;
Key分區(qū)
按照KEY進行分區(qū)類似于按照HASH分區(qū),除了HASH分區(qū)使用的用戶定義的表達式,而KEY分區(qū)的 哈希函數(shù)是由MySQL
服務(wù)器提供。MySQL 簇(Cluster)使用函數(shù)MD5()來實現(xiàn)KEY分區(qū);對于使用其他存儲引擎的表,服務(wù)器使用其自己內(nèi)部的
哈希函數(shù),這些函數(shù)是基于與PASSWORD()一樣的運算法則。
Key分區(qū)與Hash分區(qū)很相似,只是Hash函數(shù)不同,定義時把Hash關(guān)鍵字替換成Key即可,同樣Key分區(qū)也有對應與線性Hash的線性Key分區(qū)方法。
CREATE TABLE tk (
col1 INT NOT NULL,
col2 CHAR(5),
col3 DATE
)
PARTITION BY LINEAR KEY (col1)
PARTITIONS 3;
另外,當表存在主鍵或唯一索引時可省略Key括號內(nèi)的列名,Mysql將按照主鍵-唯一索引的順序選擇,當找不到唯一索引時報錯。
子分區(qū)
子分區(qū)是分區(qū)表中每個分區(qū)的再次分割。創(chuàng)建子分區(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 p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
和
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);
需要注意的是:每個分區(qū)的子分區(qū)數(shù)必須相同。如果在一個分區(qū)表上的任何分區(qū)上使用SUBPARTITION來明確定義任何子分區(qū),那么就必須定義所有的子分區(qū),且必須指定一個全表唯一的名字。
分區(qū)表的使用及查詢優(yōu)化
根據(jù)實際情況選擇分區(qū)方法
對現(xiàn)有表分區(qū)的原則與傳統(tǒng)分表一樣。
傳統(tǒng)的按照增量區(qū)間分表對應于分區(qū)的Range分區(qū),比如對表的訪問多是近期產(chǎn)生的新數(shù)據(jù),歷史數(shù)據(jù)訪問較少,則可以按一定時間段(比如年或月)或一定數(shù)量(比如100萬)對表分區(qū),具體根據(jù)哪種取決于表索引結(jié)構(gòu)。分區(qū)后最后一個分區(qū)即為近期產(chǎn)生的數(shù)據(jù),當一段時間過后數(shù)據(jù)量再次變大,可對最后一個分區(qū)重新分區(qū)(REORGANIZE PARTITION)把一段時間(一年或一月)或一定數(shù)量(比如100萬)的數(shù)據(jù)分離出去。
傳統(tǒng)的散列方法分表對應于分區(qū)的Hash/Key分區(qū),具體方法上面已經(jīng)介紹過。
查詢優(yōu)化
分區(qū)的目的是為了提高查詢效率,如果查詢范圍是所有分區(qū)那么就說明分區(qū)沒有起到作用,我們用explain partitions命令來查看SQL對于分區(qū)的使用情況。
一般來說,就是在where條件中加入分區(qū)列。
比如表salaries結(jié)構(gòu)為:
mysql> show create table salaries\G;
*************************** 1. row ***************************
Table: salaries
Create Table: CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (year(from_date))
(PARTITION p1 VALUES LESS THAN (1985) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (1986) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (1987) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (1988) ENGINE = InnoDB,
PARTITION p5 VALUES LESS THAN (1989) ENGINE = InnoDB,
PARTITION p6 VALUES LESS THAN (1990) ENGINE = InnoDB,
PARTITION p7 VALUES LESS THAN (1991) ENGINE = InnoDB,
PARTITION p8 VALUES LESS THAN (1992) ENGINE = InnoDB,
PARTITION p9 VALUES LESS THAN (1993) ENGINE = InnoDB,
PARTITION p10 VALUES LESS THAN (1994) ENGINE = InnoDB,
PARTITION p11 VALUES LESS THAN (1995) ENGINE = InnoDB,
PARTITION p12 VALUES LESS THAN (1996) ENGINE = InnoDB,
PARTITION p13 VALUES LESS THAN (1997) ENGINE = InnoDB,
PARTITION p14 VALUES LESS THAN (1998) ENGINE = InnoDB,
PARTITION p15 VALUES LESS THAN (1999) ENGINE = InnoDB,
PARTITION p16 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION p17 VALUES LESS THAN (2001) ENGINE = InnoDB,
PARTITION p18 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
則下面的查詢沒有利用分區(qū),因為partitions中包含了所有的分區(qū):
mysql> explain partitions select * from salaries where salary > 100000\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: salaries
partitions: p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2835486
Extra: Using where
只有在where條件中加入分區(qū)列才能起到作用,過濾掉不需要的分區(qū):
mysql> explain partitions select * from salaries where salary > 100000 and from_date > '1998-01-01'\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: salaries
partitions: p15,p16,p17,p18
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1152556
Extra: Using where
與普通搜索一樣,在運算符左側(cè)使用函數(shù)將使分區(qū)過濾失效,即使與分區(qū)函數(shù)想同也一樣:
mysql> explain partitions select * from salaries where salary > 100000 and year(from_date) > 1998\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: salaries
partitions: p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2835486
Extra: Using where
分區(qū)和分表的比較
- 傳統(tǒng)分表后,
count、sum等統(tǒng)計操作只能對所有切分表進行操作后之后在應用層再次計算得出最后統(tǒng)計數(shù)據(jù)。而分區(qū)表則不受影響,可直接統(tǒng)計。
Queries involving aggregate functions such as SUM() and COUNT() can easily be parallelized. A simple example of such a query might be SELECT salesperson_id, COUNT(orders) as order_total FROM sales GROUP BY salesperson_id;. By “parallelized,” we mean that
the query can be run simultaneously on each partition, and the final result obtained merely by summing the results obtained for all partitions.
-
分區(qū)對原系統(tǒng)改動最小,分區(qū)只涉及數(shù)據(jù)庫層面,應用層不需要做出改動。
-
分區(qū)有個限制是主表的所有唯一字段(包括主鍵)必須包含分區(qū)字段,而分表沒有這個限制。
-
分表包括垂直切分和水平切分,而分區(qū)只能起到水平切分的作用。
|