PostgreSQL 六大索引的方法小結(jié)
一、概覽速覽表(先有直覺)
| 索引類型 | 典型用途 | 支持唯一 | 適配查詢 | 優(yōu)缺點(diǎn)一眼看 |
|---|---|---|---|---|
| B-tree | 等值、范圍、排序、唯一約束 | ? | =, <, >, BETWEEN, ORDER BY | 默認(rèn)首選,通用;維護(hù)成本中等 |
| Hash | 純等值匹配 | ?(唯一約束由 B-tree 實(shí)現(xiàn)) | = | 僅等值;自 PG10 起 WAL 持久化;使用面窄 |
| GIN | 倒排類:jsonb、數(shù)組、全文、trigram | ? | @>, ?, ?&, @@(全文),LIKE/ILIKE(trigram) | 讀快寫慢,適合查詢多、更新少 |
| GiST | 距離/范圍/空間/相似度、KNN | ? | 范圍、相交、<-> KNN | 通用“框架”,支持多種數(shù)據(jù)類型(幾何、range、inet…) |
| SP-GiST | 前綴/空間分割(trie/k-d/四叉樹) | ? | 前綴、某些 KNN | 適合強(qiáng)分割數(shù)據(jù)(前綴搜索、坐標(biāo)) |
| BRIN | 超大表順序相關(guān)列(時(shí)間/自增ID) | ? | 大范圍掃描的快速剪枝 | 體積極小,建立/維護(hù)極輕;精度低需回檢 |
記憶法:“B 通吃、H 等值、GIN 倒排、GiST 空間、SPG 前綴、BRIN 順序”
二、B-tree(默認(rèn) & 通吃)
特性
- PostgreSQL 的
UNIQUE/主鍵約束本質(zhì)上都是 B-tree 索引。 - 適配等值/范圍/排序/聚合的常見訪問路徑與
ORDER BY … LIMIT。 - 支持覆蓋索引(
INCLUDE,用于只讀回表字段;主要用于 B-tree)。
常用語法
-- 單列 / 多列 CREATE INDEX idx_user_email ON users(email); CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC); -- 覆蓋索引(減少回表) CREATE INDEX idx_orders_status_created_inc ON orders(status, created_at) INCLUDE (amount); -- 表達(dá)式/部分索引 CREATE INDEX idx_lower_email ON users (lower(email)); CREATE INDEX idx_paid_recent ON orders (created_at) WHERE status = 'PAID';
實(shí)戰(zhàn)要點(diǎn)
- 多列 B-tree 的左前綴原則:查詢條件要盡量命中前導(dǎo)列。
- 大量
LIKE 'abc%'的前綴匹配通常也可命中 B-tree;但包含式%abc%需pg_trgm。 - 注意 NULL:唯一約束允許多行 NULL。
三、Hash(只做“等值”)
場(chǎng)景:極端等值查找且鍵寬/比較代價(jià)特殊時(shí),可能略小/略快。
限制:不支持唯一約束與范圍/排序;面窄,大多數(shù)等值場(chǎng)景仍用 B-tree。
CREATE INDEX idx_users_hash_email ON users USING hash(email);
備注:自 PG10 起 Hash 索引 WAL 持久化,可崩潰恢復(fù),但優(yōu)勢(shì)有限。
四、GIN(倒排:jsonb/數(shù)組/全文/trigram)
場(chǎng)景
jsonb包含/鍵值查詢:@>,?,?&;- 數(shù)組元素包含/交集;
- 全文檢索
to_tsvector(...) @@ to_tsquery(...); - 模糊查詢:
pg_trgm的 trigram +LIKE/ILIKE '%abc%'。
語法與 opclass
-- jsonb:兩種常用 opclass
CREATE INDEX idx_doc_gin ON docs USING gin(data jsonb_ops); -- 全功能,體積偏大
CREATE INDEX idx_doc_path ON docs USING gin(data jsonb_path_ops); -- 對(duì) @> 優(yōu)化更好
-- 數(shù)組包含
CREATE INDEX idx_tags_gin ON posts USING gin(tags);
-- 全文
CREATE INDEX idx_posts_fts ON posts USING gin(to_tsvector('simple', title || ' ' || body));
-- trigram 模糊(需擴(kuò)展)
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_user_name_trgm ON users USING gin(name gin_trgm_ops);
調(diào)優(yōu)
-- 批量重放/更新多時(shí):構(gòu)建或維護(hù)參數(shù) CREATE INDEX ... USING gin(...) WITH (fastupdate = on, gin_pending_list_limit = '512MB');
- 優(yōu)點(diǎn):讀極快(特別是包含/全文/模糊);
- 缺點(diǎn):寫慢、體積大;更適合“讀多寫少”或批量導(dǎo)入。
五、GiST(“通用”搜索樹:空間/范圍/KNN/排斥約束)
場(chǎng)景
- 幾何/地理(PostGIS)、
range、inet/cidr、相交/包含等; - KNN 最近鄰查詢:
ORDER BY <->; - 排斥約束(Exclusion Constraint):避免時(shí)間段/空間重疊(常配合
btree_gist)。
示例
-- 范圍不重疊的預(yù)約(時(shí)間區(qū)間) CREATE EXTENSION IF NOT EXISTS btree_gist; CREATE TABLE booking( room_id int, during tstzrange, EXCLUDE USING gist (room_id WITH =, during WITH &&) -- 禁止同房間時(shí)間相交 ); -- KNN:最近地點(diǎn) CREATE INDEX idx_poi_gist ON poi USING gist (geom); SELECT * FROM poi ORDER BY geom <-> ST_SetSRID(ST_MakePoint(121.5,31.2), 4326) LIMIT 20;
要點(diǎn)
- GiST 是“框架”,性能取決于具體 operator class(幾何、range 等)。
- 構(gòu)建大索引可:
WITH (buffering = on);范圍型查詢常見“回檢”。
六、SP-GiST(空間分割/前綴)
場(chǎng)景
- 前綴類數(shù)據(jù)(如手機(jī)號(hào)/URL/域名前綴)基于 trie;
- 坐標(biāo)點(diǎn)的 k-d/四叉樹等強(qiáng)分割結(jié)構(gòu)。
-- 前綴查詢 CREATE INDEX idx_phone_prefix ON users USING spgist (phone_number); SELECT * FROM users WHERE phone_number LIKE '1389%';
特點(diǎn):對(duì)分布不均勻且可遞歸分割的數(shù)據(jù)更友好;更新/插入性能通常優(yōu)于 GiST 的某些場(chǎng)景。
七、BRIN(Block Range Index:大表“順序相關(guān)”神器)
場(chǎng)景
- 超大表(千萬/億級(jí)),
created_at、自增id與物理順序相關(guān)性高; - 大范圍查詢或分段掃描,BRIN 能以極小代價(jià)快速縮小掃描頁面。
-- 典型配置:pages_per_range 控制摘要粒度(越小越精細(xì)) CREATE INDEX idx_orders_brin_created ON orders USING brin (created_at) WITH (pages_per_range = 128, autosummarize = on);
要點(diǎn)
- BRIN 只存儲(chǔ)每個(gè)范圍的 min/max 等摘要,需要回表回檢;
- 體積/維護(hù)成本極低,適合“追加寫 + 時(shí)間窗口查詢”;
- 相關(guān)性弱(數(shù)據(jù)經(jīng)常亂序?qū)懭耄r(shí)效果下降,可
CLUSTER/重寫表優(yōu)化物理順序。
八、選型決策 10 條軍規(guī)
- 能用 B-tree 先用 B-tree:等值/范圍/排序/唯一都穩(wěn)。
jsonb/數(shù)組/全文/模糊→ GIN;其中LIKE '%abc%'強(qiáng)烈建議 trigram + GIN。- 距離/空間/范圍相交/KNN → GiST(PostGIS、range、inet 等)。
- 前綴或可分割空間結(jié)構(gòu) → SP-GiST。
- 超大追加型時(shí)間/ID查詢 → BRIN。
- 純等值且確有收益證據(jù) → Hash;否則 B-tree。
- 高頻過濾 + 低選擇度 → 部分索引(
WHERE ...)勝過大而全。 - 只讀回表字段較多 → B-tree INCLUDE 做覆蓋掃描。
- 表達(dá)式要索引同款表達(dá)式(如
lower(email));否則無法命中。 - 多列順序要按查詢使用頻次/選擇度從左到右排列;避免“全吃不著”的復(fù)合索引。
九、常見坑與對(duì)癥下藥
- 模糊查詢沒走索引:
LIKE '%abc%'需pg_trgm+GIN/GiST;LIKE 'abc%'可走 B-tree。 - 大小寫不敏感:
lower(col)表達(dá)式索引 + 查詢同寫法;或用citext類型。 - 多列索引未命中:條件沒用到前導(dǎo)列;或使用了不等價(jià)的表達(dá)式/函數(shù)。
- jsonb 慢:選對(duì) opclass:
jsonb_path_ops對(duì)@>更緊湊;更新頻繁則謹(jǐn)慎使用 GIN。 - 索引暴脹:定期
VACUUM,必要時(shí)REINDEX;控制fillfactor。 - 計(jì)劃不穩(wěn)定:檢查統(tǒng)計(jì)信息與相關(guān)性(
ANALYZE、default_statistics_target);利用EXPLAIN (ANALYZE, BUFFERS)診斷。
十、實(shí)戰(zhàn)模板:一張訂單表怎么配索引
CREATE TABLE orders( id bigserial PRIMARY KEY, user_id bigint NOT NULL, status text NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), amount numeric(12,2) NOT NULL, items jsonb, -- 訂單明細(xì)(jsonb) tags text[] -- 標(biāo)簽 ); -- 1) 用戶最近訂單(分頁/排序) CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC); -- 2) 狀態(tài) + 時(shí)間窗口統(tǒng)計(jì)(覆蓋金額) CREATE INDEX idx_orders_status_created_inc ON orders(status, created_at) INCLUDE (amount); -- 3) jsonb 包含查找(items 內(nèi)含某 SKU) CREATE INDEX idx_orders_items_path ON orders USING gin(items jsonb_path_ops); -- 4) 標(biāo)簽包含任一/全部 CREATE INDEX idx_orders_tags_gin ON orders USING gin(tags); -- 5) 超大表時(shí)間過濾的剪枝 CREATE INDEX idx_orders_brin_created ON orders USING brin (created_at) WITH (pages_per_range=128, autosummarize=on);
十一、性能與維護(hù)清單
- 分析與觀測(cè):
EXPLAIN (ANALYZE, BUFFERS),pg_stat_statements,pg_stat_all_indexes。 - 維護(hù):
VACUUM (ANALYZE)、高寫入期適當(dāng)增大maintenance_work_mem;大索引可并行創(chuàng)建:CREATE INDEX CONCURRENTLY(無鎖長(zhǎng)事務(wù),但更慢)。 - 參數(shù)提示:順序 I/O 多可調(diào)低
random_page_cost;SSD 環(huán)境可適當(dāng)下調(diào)以提高索引傾向。 - 物理順序:時(shí)間序列表可偶爾
CLUSTER或重寫,提高 BRIN/JIT 效果與熱點(diǎn)局部性。
十二、快速對(duì)照:你在查什么,就選什么
WHERE a = ?/ORDER BY a/BETWEEN→ B-treeWHERE col @> '{"k":"v"}'::jsonb/tags @> '{x}'→ GIN(jsonb/數(shù)組)title @@ to_tsquery('...')→ GIN(全文)name ILIKE '%abc%'→ GIN + pg_trgmgeom <-> point最近點(diǎn) → GiST + KNNtsrange && ?不重疊預(yù)約 → GiST + 排斥約束phone LIKE '1389%'→ SP-GiST(或 B-tree 也可)WHERE created_at BETWEEN ...(億級(jí)表) → BRIN
到此這篇關(guān)于PostgreSQL 六大索引的方法小結(jié)的文章就介紹到這了,更多相關(guān)PostgreSQL 索引內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- PostgreSQL中GIN索引的三種使用場(chǎng)景
- 使用PostgreSQL創(chuàng)建高級(jí)搜索引擎的代碼示例
- PostgreSQL索引失效會(huì)發(fā)生什么
- PostgreSQL長(zhǎng)事務(wù)與失效的索引查詢淺析介紹
- PostgreSQL游標(biāo)與索引選擇實(shí)例詳細(xì)介紹
- postgresql 索引之 hash的使用詳解
- PostgreSql 重建索引的操作
- PostgreSQL模糊匹配走索引的操作
- postgresql通過索引優(yōu)化查詢速度操作
- PostgreSQL 查看數(shù)據(jù)庫(kù),索引,表,表空間大小的示例代碼
相關(guān)文章
PostgreSQL實(shí)現(xiàn)交叉表(行列轉(zhuǎn)換)的5種方法示例
這篇文章主要給大家介紹了關(guān)于PostgreSQL實(shí)現(xiàn)交叉表(行列轉(zhuǎn)換)的5種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
PostgreSQL中進(jìn)行數(shù)據(jù)導(dǎo)入和導(dǎo)出的示例代碼
在數(shù)據(jù)庫(kù)管理中,數(shù)據(jù)的導(dǎo)入和導(dǎo)出是非常常見的操作,特別是在 PostgreSQL 中,提供了多種工具和方法來實(shí)現(xiàn)數(shù)據(jù)的有效管理,本文將詳細(xì)介紹在 PostgreSQL 中如何進(jìn)行數(shù)據(jù)導(dǎo)入和導(dǎo)出,并給出具體的命令及示例,需要的朋友可以參考下2026-03-03
PostgreSQL數(shù)據(jù)庫(kù)中如何保證LIKE語句的效率(推薦)
這篇文章主要介紹了PostgreSQL數(shù)據(jù)庫(kù)中如何保證LIKE語句的效率,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
PostgreSQL中實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)監(jiān)控和預(yù)警的步驟詳解
在 PostgreSQL 中實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)監(jiān)控和預(yù)警是確保數(shù)據(jù)庫(kù)性能和數(shù)據(jù)完整性的關(guān)鍵任務(wù),以下將詳細(xì)討論如何實(shí)現(xiàn)此目標(biāo),并提供相應(yīng)的解決方案和具體示例,需要的朋友可以參考下2024-07-07
PostgreSQ數(shù)據(jù)庫(kù)實(shí)現(xiàn)在Windows上異地自動(dòng)備份指南的詳細(xì)教程
這篇文章主要為大家詳細(xì)介紹了如何在Windows系統(tǒng)上實(shí)現(xiàn)PostgreSQL數(shù)據(jù)庫(kù)的異地自動(dòng)備份,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-12-12
postgreSQL自動(dòng)生成隨機(jī)數(shù)值的實(shí)例
這篇文章主要介紹了postgreSQL自動(dòng)生成隨機(jī)數(shù)值的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
開源數(shù)據(jù)庫(kù)postgreSQL13在麒麟v10sp1源碼安裝過程詳解
這篇文章主要介紹了開源數(shù)據(jù)庫(kù)postgreSQL13在麒麟v10sp1源碼安裝過程詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01

