什么是分庫(kù)分表
????????分庫(kù)分表是一種數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì)的方法,用于應(yīng)對(duì)大規(guī)模數(shù)據(jù)的存儲(chǔ)和查詢。當(dāng)單個(gè)數(shù)據(jù)庫(kù)的存儲(chǔ)容量或查詢性能無(wú)法滿足需求時(shí),可以通過(guò)將數(shù)據(jù)分散存儲(chǔ)在多個(gè)數(shù)據(jù)庫(kù)服務(wù)器上,以提高系統(tǒng)的可擴(kuò)展性和性能。
????????分庫(kù)分表通常包括兩個(gè)步驟:分庫(kù)和分表。
分庫(kù)
????????分庫(kù)是指將單個(gè)數(shù)據(jù)庫(kù)按照一定規(guī)則劃分為多個(gè)數(shù)據(jù)庫(kù),每個(gè)數(shù)據(jù)庫(kù)可以存儲(chǔ)一部分?jǐn)?shù)據(jù)。這樣可以減少單個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)量,提高查詢效率。常見(jiàn)的分庫(kù)方式包括垂直分庫(kù)和水平分庫(kù)。
????????垂直分庫(kù)是指按照功能模塊或業(yè)務(wù)領(lǐng)域?qū)?shù)據(jù)分成多個(gè)數(shù)據(jù)庫(kù)。例如,可以將訂單數(shù)據(jù)、用戶數(shù)據(jù)、商品數(shù)據(jù)分別存儲(chǔ)在不同的數(shù)據(jù)庫(kù)中。
????????水平分庫(kù)是指按照數(shù)據(jù)特征將數(shù)據(jù)分成多個(gè)數(shù)據(jù)庫(kù),例如按照時(shí)間、地理位置等。例如,可以將訂單數(shù)據(jù)按照月份分別存儲(chǔ)在不同的數(shù)據(jù)庫(kù)中。
分表
????????分表是指將單個(gè)表按照一定規(guī)則劃分為多個(gè)表,每個(gè)表可以存儲(chǔ)一部分?jǐn)?shù)據(jù)。這樣可以減少單個(gè)表的數(shù)據(jù)量,提高查詢效率。常見(jiàn)的分表方式包括垂直分表和水平分表。
????????垂直分表是指按照功能模塊或業(yè)務(wù)領(lǐng)域?qū)⒈矸殖啥鄠€(gè)部分。例如,可以將訂單表按照訂單狀態(tài)分成多個(gè)部分。
????????水平分表是指按照數(shù)據(jù)特征將表分成多個(gè)部分,例如按照時(shí)間、地理位置等。例如,可以將訂單表按照月份分別存儲(chǔ)在不同的表中。
從PostgreSQL 11開(kāi)始,就有三種表分區(qū):
????????1. 范圍分區(qū)(Range Partition)
????????范圍分區(qū)是將表按照某個(gè)列的值劃分成一段或多段。每個(gè)分區(qū)的端點(diǎn)值存儲(chǔ)在 pg_partition_range 系統(tǒng)表中。范圍分區(qū)支持基于時(shí)間戳的自動(dòng)分區(qū),例如根據(jù)日期列自動(dòng)創(chuàng)建每天、每月、每年等分區(qū)。
????????2. 列表分區(qū)(List Partition)
????????列表分區(qū)是將表按照某個(gè)列的值存儲(chǔ)在數(shù)組中,每個(gè)分區(qū)的值存儲(chǔ)在 pg_partition_list 系統(tǒng)表中。列表分區(qū)的支持比較靈活,可以自定義分區(qū)值,也可以使用預(yù)先定義好的列表進(jìn)行分區(qū)。
????????3. 哈希分區(qū)(Hash Partition)
????????哈希分區(qū)是將表按照某個(gè)列的值進(jìn)行哈希運(yùn)算,將結(jié)果映射到不同的分區(qū)。哈希分區(qū)可以使用任何哈希函數(shù),例如 MD5、SHA1 等。哈希分區(qū)的優(yōu)點(diǎn)是可以平均分布數(shù)據(jù),避免某個(gè)分區(qū)存儲(chǔ)過(guò)多數(shù)據(jù),提高查詢效率。
示例
1. 創(chuàng)建主表
????????首先,我們需要?jiǎng)?chuàng)建一個(gè)主表,用于存儲(chǔ)所有分表的公共字段和索引。在示例中,我們創(chuàng)建一個(gè)名為 customers 的表,其中包含 id、name、age 和 address 列。
testdb=# CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT NOT NULL,
address VARCHAR(100) NOT NULL
);
2. 創(chuàng)建分表
????????接下來(lái),我們需要?jiǎng)?chuàng)建多個(gè)分表,每個(gè)分表都包含主表的所有字段和額外的特定字段。在示例中,我們創(chuàng)建年齡分區(qū)表
user=# create table customers_10 () inherits (customers);
CREATE TABLE
user=# create table customers_20 () inherits (customers);
CREATE TABLE
user=# create table customers_30 () inherits (customers);
CREATE TABLE
user=#
user=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------------------+----------+-------
public | customers | table | user
public | customers_10 | table | user
public | customers_20 | table | user
public | customers_30 | table | user
3.?定義分表規(guī)則
????????使用 PostgreSQL 提供的分表規(guī)則(partitioning)功能,定義如何將數(shù)據(jù)分配到不同的分表中。在示例中,我們使用 AGE 列作為分表規(guī)則,將數(shù)據(jù)分配到 customers_age 分表中。
首先創(chuàng)建一個(gè)function,年齡為 (0,10), [10,20), [20, ...)分別插入三張不同的表里。
然后創(chuàng)建一個(gè)trigger,在插入到customers之前開(kāi)始執(zhí)行這個(gè)function。
這樣子當(dāng)我們向這個(gè)customers表插入數(shù)據(jù)的時(shí)候
user=# create or replace function customers_partition_trigger()
returns trigger as $$
begin
if NEW.age < 10 then
insert into customers_10 values (NEW.*);
elseif NEW.age < 20 then
insert into customers_20 values (NEW.*);
else insert into customers_30 values (NEW.*);
end if;
return null;
end;
$$
language plpgsql;
CREATE FUNCTION
user=# create trigger insert_customers_partition_trigger
user-# before insert on customers
user-# for each row execute procedure customers_partition_trigger();
CREATE TRIGGER
4. 向表中插入數(shù)據(jù),這里數(shù)據(jù)仍會(huì)顯示在父表中,但是實(shí)際上父表僅僅作為整個(gè)分區(qū)表結(jié)構(gòu)的展示,實(shí)際插入的記錄是保存在子表中。
user=# INSERT INTO customers VALUES (1, 'Alice', 25, 'New York');
INSERT 0 0
user=# INSERT INTO customers VALUES (2, 'Bob', 35, 'San Francisco');
INSERT 0 0
user=# INSERT INTO customers VALUES (3, 'Charlie', 18, 'Chicago');
INSERT 0 0
user=# INSERT INTO customers VALUES (3, 'Charlie', 18, 'Chicago');
INSERT 0 0
user=# select * from customers;
id | name | age | address
----+---------+-----+---------------
3 | Charlie | 18 | Chicago
3 | Charlie | 18 | Chicago
1 | Alice | 25 | New York
2 | Bob | 35 | San Francisco
(4 rows)
user=# select * from customers_10;
id | name | age | address
----+------+-----+---------
(0 rows)
user=# select * from customers_20;
id | name | age | address
----+---------+-----+---------
3 | Charlie | 18 | Chicago
3 | Charlie | 18 | Chicago
(2 rows)
user=# select * from customers_30;
id | name | age | address
----+-------+-----+---------------
1 | Alice | 25 | New York
2 | Bob | 35 | San Francisco
(2 rows)
5. 設(shè)置分表約束,加快查詢效率。因?yàn)槿绻樵冎鞅淼脑?,?huì)直接掃描所有的子表來(lái)查詢,但是如果加上constraint的話,會(huì)允許規(guī)劃器根據(jù)條件查詢對(duì)應(yīng)的子分區(qū),在數(shù)據(jù)很多的情況下可以加快查詢速度。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-631891.html
user=# alter table customers_10
user-# add constraint customers_10_check_age_key
user-# check (age < 10);
ALTER TABLE
user=# alter table customers_20
user-# add constraint customers_20_check_age_key
user-# check (age < 20);
ALTER TABLE
user=# alter table customers_30
user-# add constraint customers_30_check_age_key
user-# check (age < 30);
ALTER TABLE
優(yōu)缺點(diǎn)
分庫(kù)分表都有 一定的優(yōu)缺點(diǎn),下面來(lái)盤(pán)點(diǎn)下。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-631891.html
優(yōu)點(diǎn)
- 提高系統(tǒng)可擴(kuò)展性:通過(guò)將數(shù)據(jù)分散存儲(chǔ)在多個(gè)數(shù)據(jù)庫(kù)服務(wù)器上,可以提高系統(tǒng)的可擴(kuò)展性,方便擴(kuò)展存儲(chǔ)容量和處理能力。
- 提高系統(tǒng)性能:通過(guò)將數(shù)據(jù)分散存儲(chǔ)在多個(gè)數(shù)據(jù)庫(kù)服務(wù)器上,可以提高系統(tǒng)的性能,減少單個(gè)數(shù)據(jù)庫(kù)的壓力。
- 降低數(shù)據(jù)冗余:通過(guò)將數(shù)據(jù)分散存儲(chǔ)在多個(gè)數(shù)據(jù)庫(kù)服務(wù)器上,可以降低數(shù)據(jù)冗余,減少數(shù)據(jù)丟失的風(fēng)險(xiǎn)。
缺點(diǎn)
- 復(fù)雜性:分庫(kù)分表需要對(duì)數(shù)據(jù)進(jìn)行劃分和維護(hù),增加了系統(tǒng)的復(fù)雜性和維護(hù)成本。
- 數(shù)據(jù)一致性:分庫(kù)分表可能導(dǎo)致數(shù)據(jù)不一致,需要額外的機(jī)制來(lái)保證數(shù)據(jù)的一致性。
- 事務(wù)處理:分庫(kù)分表可能會(huì)影響事務(wù)的處理,需要額外的機(jī)制來(lái)支持跨庫(kù)的事務(wù)處理。
到了這里,關(guān)于[SQL系列] 從頭開(kāi)始學(xué)PostgreSQL 分庫(kù)分表的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!