PostgreSQL表分區(qū)的三種方式和操作方法
一、什么是表分區(qū)?它和分庫(kù)分表有什么區(qū)別?
1.1 什么是表分區(qū)(Table Partitioning)?
表分區(qū)是數(shù)據(jù)庫(kù)的一種物理設(shè)計(jì)技術(shù),它將一個(gè)大表從邏輯上視為一個(gè)整體,但從物理上拆分成多個(gè)子表(分區(qū)),每個(gè)分區(qū)存儲(chǔ)一部分?jǐn)?shù)據(jù)。
- 邏輯上:你仍然像操作一張表一樣查詢它
- 物理上:數(shù)據(jù)分散在多個(gè)子表中,按規(guī)則存儲(chǔ)
- ? 舉個(gè)例子:
把jgpt_jzd_test按年份拆成p2023、p2024、p2025三個(gè)分區(qū),查詢時(shí)仍用SELECT * FROM jgpt_jzd_test,但數(shù)據(jù)庫(kù)只掃描相關(guān)分區(qū)。
1.2 表分區(qū) vs 分庫(kù)分表:關(guān)鍵區(qū)別
| 對(duì)比項(xiàng) | 表分區(qū) | 分庫(kù)分表 |
|---|---|---|
| 實(shí)現(xiàn)層級(jí) | 數(shù)據(jù)庫(kù)內(nèi)部(單庫(kù)) | 應(yīng)用層或中間件(跨庫(kù)) |
| 透明性 | 高(應(yīng)用無(wú)感知) | 低(需改代碼) |
| 管理復(fù)雜度 | 低(自動(dòng)路由) | 高(需路由規(guī)則) |
| 事務(wù)支持 | 完整支持 | 跨庫(kù)事務(wù)復(fù)雜 |
| 適用場(chǎng)景 | 單表過(guò)大(百萬(wàn)~億級(jí)) | 數(shù)據(jù)量極大(TB級(jí)+) |
| 技術(shù)棧 | PostgreSQL、MySQL 8.0+ | ShardingSphere、MyCat |
? 簡(jiǎn)單說(shuō):
- 表分區(qū)是“數(shù)據(jù)庫(kù)幫你拆”
- 分庫(kù)分表是“你自己寫代碼拆”
二、表分區(qū)的優(yōu)缺點(diǎn)與使用場(chǎng)景
優(yōu)點(diǎn)
| 優(yōu)勢(shì) | 說(shuō)明 |
|---|---|
| 查詢性能提升 | 分區(qū)剪枝(Partition Pruning)自動(dòng)跳過(guò)無(wú)關(guān)分區(qū) |
| 數(shù)據(jù)管理高效 | 刪除舊數(shù)據(jù)從 DELETE 變?yōu)?nbsp;DROP PARTITION(秒級(jí)) |
| 維護(hù)更方便 | 可對(duì)單個(gè)分區(qū)做 VACUUM、ANALYZE、備份 |
| I/O 分散 | 不同分區(qū)可分布到不同磁盤(高級(jí)用法) |
缺點(diǎn)
| 缺點(diǎn) | 說(shuō)明 |
|---|---|
| 全表掃描變慢 | 需掃描所有分區(qū),元數(shù)據(jù)開(kāi)銷增加 |
| 分區(qū)鍵固定 | 一旦選定(如 gmt_create),不能更改 |
| 管理復(fù)雜度上升 | 需定期創(chuàng)建新分區(qū) |
| 不支持主鍵跨分區(qū) | 主鍵必須包含分區(qū)鍵 |
三、PostgreSQL 表分區(qū)的三種方式
PostgreSQL 支持三種分區(qū)策略:
1.Range 分區(qū)(按范圍)
- 適用:時(shí)間、數(shù)值范圍
- 示例:按
gmt_create按年/月分區(qū) - 語(yǔ)法:
PARTITION BY RANGE (gmt_create)
2.List 分區(qū)(按枚舉值)
- 適用:固定分類,如省份、狀態(tài)
- 示例:按
province分區(qū) - 語(yǔ)法:
PARTITION BY LIST (province)
3.Hash 分區(qū)(按哈希值)
- 適用:數(shù)據(jù)均勻分布,無(wú)明顯查詢模式
- 示例:按
id哈希分 4 份 - 語(yǔ)法:
PARTITION BY HASH (id)
四、實(shí)戰(zhàn):jgpt_jzd_test表分區(qū)操作全流程
將 3000 萬(wàn)+ 的 jgpt_jzd_test 表改造為按年分區(qū)的分區(qū)表。
步驟 1:創(chuàng)建分區(qū)主表
-- 創(chuàng)建主表(邏輯表,不存數(shù)據(jù))
CREATE TABLE jgpt_jzd_test_partitioned (
id varchar(32),
jzdbh varchar(255),
xzb varchar(255),
yzb varchar(255),
htxxid varchar(255),
gmt_create timestamp(6) NOT NULL, -- 必須 NOT NULL
gmt_modified timestamp(6),
del_flag varchar,
created_user_id varchar(255),
created_user varchar(255),
last_modified_user_id varchar(255),
last_modified_user varchar(255),
dkh varchar(255),
dkms varchar(255),
batchnum varchar(255)
) PARTITION BY RANGE (gmt_create);
步驟 2:創(chuàng)建子分區(qū)(按年)
-- 2023 年分區(qū)
CREATE TABLE jgpt_jzd_test_p2023
PARTITION OF jgpt_jzd_test_partitioned
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
-- 2024 年分區(qū)
CREATE TABLE jgpt_jzd_test_p2024
PARTITION OF jgpt_jzd_test_partitioned
FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
-- 2025 年分區(qū)
CREATE TABLE jgpt_jzd_test_p2025
PARTITION OF jgpt_jzd_test_partitioned
FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');步驟 3:遷移數(shù)據(jù)
-- 從舊表插入到新分區(qū)表(自動(dòng)路由) INSERT INTO jgpt_jzd_test_partitioned SELECT * FROM jgpt_jzd_test;
步驟 4:創(chuàng)建索引
-- 在主表創(chuàng)建索引,所有分區(qū)自動(dòng)繼承 CREATE INDEX idx_jgpt_jzd_test_htxxid ON jgpt_jzd_test_partitioned (htxxid);
步驟 5:切換表名(原子操作)
-- 1. 備份原表 ALTER TABLE jgpt_jzd_test RENAME TO jgpt_jzd_test_backup; -- 2. 新表啟用原名 ALTER TABLE jgpt_jzd_test_partitioned RENAME TO jgpt_jzd_test;
? 至此,jgpt_jzd_test 已是分區(qū)表!
五、驗(yàn)證表分區(qū)是否成功
1. 查看分區(qū)結(jié)構(gòu)
-- 查詢系統(tǒng)表
SELECT
inhrelid::regclass AS child_table,
inhparent::regclass AS parent_table
FROM pg_inherits
WHERE inhparent = 'jgpt_jzd_test'::regclass;
2. 驗(yàn)證分區(qū)剪枝是否生效
explain SELECT COUNT(*) FROM jgpt_jzd_test WHERE gmt_create >= '2025-01-01' AND gmt_create < '2026-01-01';

可以看到只查詢了jgpt_jzd_test_p2025一張分區(qū)表
六、安全刪除分區(qū):DETACHvsDROP(關(guān)鍵區(qū)別)
在表分區(qū)的日常維護(hù)中,刪除歷史數(shù)據(jù)是一個(gè)高頻操作。PostgreSQL 提供了兩種方式來(lái)“移除”分區(qū),但它們的安全性、可逆性和使用場(chǎng)景完全不同。
我們以 jgpt_jzd_test_p2024 分區(qū)為例,對(duì)比兩種操作:
1.DETACH PARTITION—— 安全的“解綁”操作
ALTER TABLE jgpt_jzd_test_partitioned
DETACH PARTITION jgpt_jzd_test_p2024;操作特點(diǎn):
- 數(shù)據(jù)不會(huì)丟失!
jgpt_jzd_test_p2024表變成一個(gè)獨(dú)立的普通表- 主表
jgpt_jzd_test_partitioned不再包含該分區(qū)的數(shù)據(jù)- 可隨時(shí)對(duì)
jgpt_jzd_test_p2024進(jìn)行查詢、導(dǎo)出、備份或重新掛載
適用場(chǎng)景:
- 需要?dú)w檔數(shù)據(jù)
- 刪除前做審計(jì)或備份
- 不確定是否永久刪除
-- 確認(rèn)無(wú)誤后,再刪除 DROP TABLE jgpt_jzd_test_p2024;
? 推薦做法:先 DETACH,再 DROP,避免誤刪。
2.DROP PARTITION—— 永久刪除
ALTER TABLE jgpt_jzd_test_partitioned
DROP PARTITION jgpt_jzd_test_p2024;操作特點(diǎn):
- 數(shù)據(jù)立即永久丟失!無(wú)法通過(guò)
DROP回滾- 相當(dāng)于執(zhí)行了
DROP TABLE,文件被物理刪除- 無(wú)法恢復(fù)(除非有數(shù)據(jù)庫(kù)備份)
適用場(chǎng)景:
- 確認(rèn)數(shù)據(jù)不再需要
- 緊急釋放磁盤空間
- 自動(dòng)化腳本中已確認(rèn)安全
對(duì)比總結(jié)
| 操作 | 數(shù)據(jù)是否保留 | 是否可逆 | 安全性 | 推薦使用場(chǎng)景 |
|---|---|---|---|---|
DETACH PARTITION | ? 保留 | ? 可逆 | 高 | 所有刪除操作的首選 |
DROP PARTITION | ? 丟失 | ? 不可逆 | 低 | 確認(rèn)永久刪除 |
七、自己的理解
1.表分區(qū)之后,你在datagrip或navicat里面看到的還是一張表,數(shù)據(jù)也都在這張表里,但實(shí)際上這張表是主表,沒(méi)有存儲(chǔ)數(shù)據(jù)。
2.數(shù)據(jù)實(shí)際存儲(chǔ)在分區(qū)表里,例如jgpt_jzd_test_p2024,因此代碼里面是可以直接調(diào)用這張表的
3.平時(shí)基本不用管分區(qū)表,正常使用主表就行了,比如你插入數(shù)據(jù),直接往jgpt_jzd_test插入,數(shù)據(jù)庫(kù)會(huì)根據(jù)你的gmt字段自動(dòng)插入到相應(yīng)的分區(qū)表里面,平時(shí)使用基本是無(wú)感的
總結(jié):我的認(rèn)知升級(jí)
| 舊認(rèn)知 | 新認(rèn)知 |
|---|---|
| 分區(qū)就是“拆表” | 分區(qū)是“邏輯統(tǒng)一,物理分離” |
| 數(shù)據(jù)存在主表 | 主表是“空殼”,數(shù)據(jù)在分區(qū) |
| 只能查主表 | 可直查分區(qū),性能更優(yōu) |
| 分區(qū)很復(fù)雜 | 日常使用完全無(wú)感 |
到此這篇關(guān)于PostgreSQL表分區(qū)的三種方式和操作方法的文章就介紹到這了,更多相關(guān)PostgreSQL表分區(qū)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
postgresql 13.1 insert into select并行查詢的實(shí)現(xiàn)
這篇文章主要介紹了解決postgresql insert into select無(wú)法使用并行查詢的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
使用PostgreSQL為表或視圖創(chuàng)建備注的操作
這篇文章主要介紹了使用PostgreSQL為表或視圖創(chuàng)建備注的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
PostgreSQL 更新視圖腳本的注意事項(xiàng)說(shuō)明
這篇文章主要介紹了PostgreSQL 更新視圖腳本的注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
PostgreSQL如何按照某一字段去重,并顯示其他字段信息
這篇文章主要介紹了PostgreSQL如何按照某一字段去重,并顯示其他字段信息問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
如何將excel表格數(shù)據(jù)導(dǎo)入postgresql數(shù)據(jù)庫(kù)
這篇文章主要介紹了如何將excel表格數(shù)據(jù)導(dǎo)入postgresql數(shù)據(jù)庫(kù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
postgresql數(shù)據(jù)添加兩個(gè)字段聯(lián)合唯一的操作
這篇文章主要介紹了postgresql數(shù)據(jù)添加兩個(gè)字段聯(lián)合唯一的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02

