PostgreSQL 聯合索引生效條件

最近面試的時候,總會遇到一個問題

在 PostgreSQL 中,聯合索引在什么條件下會生效?

特此記錄~

前置信息

數據庫版本

  • PostgreSQL 14.13, compiled by Visual C++ build 1941, 64-bit

建表語句

CREATE TABLE people (id SERIAL PRIMARY KEY,city VARCHAR(50),name VARCHAR(50),age INT
);CREATE INDEX idx_city_name_age ON people(city, name, age);-- 插入數據
INSERT INTO people (city, name, age) VALUES
('Beijing', 'Tom', 18),
('Beijing', 'Tom', 20),
('Beijing', 'Jerry', 18),
('Shanghai', 'Jerry', 22),
('Shanghai', 'Alice', 25),
('Guangzhou', 'Bob', 30);

查看索引是否命中

EXPLAIN ANALYZE SELECT * FROM people WHERE city = 'Beijing' AND name = 'Tom' AND age = 20;

結果

Index Scan using idx_city_name_age on people  (cost=0.15..8.17 rows=1 width=244) (actual time=0.012..0.013 rows=1 loops=1)Index Cond: (((city)::text = 'Beijing'::text) AND ((name)::text = 'Tom'::text) AND (age = 20))
Planning Time: 0.074 ms
Execution Time: 0.022 ms

我們可以清楚的看到索引命中了,那么改變一下 WHERE 條件呢,例如:

EXPLAIN ANALYZE SELECT * FROM people WHERE city = 'Beijing';
EXPLAIN ANALYZE SELECT * FROM people WHERE name = 'Tom';
EXPLAIN ANALYZE SELECT * FROM people WHERE age = 20;
EXPLAIN ANALYZE SELECT * FROM people WHERE name = 'Tom' and age = 20;
EXPLAIN ANALYZE SELECT * FROM people WHERE city = 'Beijing' and name = 'Tom';
EXPLAIN ANALYZE SELECT * FROM people WHERE city = 'Beijing' and age = 20;

分別執行一下,查看結果

Bitmap Heap Scan on people  (cost=4.16..9.50 rows=2 width=244) (actual time=0.014..0.014 rows=3 loops=1)Recheck Cond: ((city)::text = 'Beijing'::text)Heap Blocks: exact=1->  Bitmap Index Scan on idx_city_name_age  (cost=0.00..4.16 rows=2 width=0) (actual time=0.011..0.011 rows=3 loops=1)Index Cond: ((city)::text = 'Beijing'::text)
Planning Time: 0.056 ms
Execution Time: 0.031 ms-------------------------------------------------------------------------------
Seq Scan on people  (cost=0.00..13.75 rows=2 width=244) (actual time=0.009..0.010 rows=2 loops=1)Filter: ((name)::text = 'Tom'::text)Rows Removed by Filter: 4
Planning Time: 0.060 ms
Execution Time: 0.020 ms-------------------------------------------------------------------------------
Seq Scan on people  (cost=0.00..13.75 rows=2 width=244) (actual time=0.008..0.009 rows=1 loops=1)Filter: (age = 20)Rows Removed by Filter: 5
Planning Time: 0.054 ms
Execution Time: 0.017 ms-------------------------------------------------------------------------------
Seq Scan on people  (cost=0.00..14.50 rows=1 width=244) (actual time=0.011..0.012 rows=1 loops=1)Filter: (((name)::text = 'Tom'::text) AND (age = 20))Rows Removed by Filter: 5
Planning Time: 0.056 ms
Execution Time: 0.020 ms-------------------------------------------------------------------------------
Index Scan using idx_city_name_age on people  (cost=0.15..8.17 rows=1 width=244) (actual time=0.015..0.016 rows=2 loops=1)Index Cond: (((city)::text = 'Beijing'::text) AND ((name)::text = 'Tom'::text))
Planning Time: 0.057 ms
Execution Time: 0.026 ms-------------------------------------------------------------------------------
Index Scan using idx_city_name_age on people  (cost=0.15..8.18 rows=1 width=244) (actual time=0.018..0.019 rows=1 loops=1)Index Cond: (((city)::text = 'Beijing'::text) AND (age = 20))
Planning Time: 0.062 ms
Execution Time: 0.031 ms

查看結果,我們發現,WHERE條件后面帶上 city字段的 SQL 語句全部走了索引,其余字段全表掃描。

看到這兒,可能可以得出結論,PG 數據庫聯合索引遵循最左匹配原則,只有最左邊的字段存在才能命中索引。

這里才幾條數據,讓我們增加 people 表中的數據

INSERT INTO people (city, name, age)
SELECT-- 隨機分配 3 個城市CASE (random()*3)::intWHEN 0 THEN 'Beijing'WHEN 1 THEN 'Shanghai'ELSE 'Guangzhou'END,-- 隨機分配 10 個名字CASE (random()*10)::intWHEN 0 THEN 'Tom'WHEN 1 THEN 'Jerry'WHEN 2 THEN 'Alice'WHEN 3 THEN 'Bob'WHEN 4 THEN 'David'WHEN 5 THEN 'Eva'WHEN 6 THEN 'John'WHEN 7 THEN 'Lily'WHEN 8 THEN 'Lucy'ELSE 'Mike'END,(random()*100)::int  -- 年齡 0~100
FROM generate_series(1, 100000);

這行 SQL 語句為 people 表增加了十萬條數據,讓我們再試試沒有 city字段的查詢語句

EXPLAIN ANALYZE SELECT * FROM people WHERE age = 18 and name = 'David';

執行結果

Bitmap Heap Scan on people  (cost=1556.38..1836.90 rows=107 width=22) (actual time=0.485..0.532 rows=80 loops=1)Recheck Cond: (((name)::text = 'David'::text) AND (age = 18))Heap Blocks: exact=78->  Bitmap Index Scan on idx_city_name_age  (cost=0.00..1556.35 rows=107 width=0) (actual time=0.477..0.477 rows=80 loops=1)Index Cond: (((name)::text = 'David'::text) AND (age = 18))
Planning Time: 0.856 ms
Execution Time: 0.549 ms

我們看到沒有 city 字段,還是走了索引。但是似乎這種方式不是高效的方式,PG 數據庫綜合考慮還是走了索引,別的情況下可能不會走索引。

但是單獨的非最左索引字段肯定不走索引,例如:

EXPLAIN ANALYZE SELECT * FROM people WHERE age = 18;
EXPLAIN ANALYZE SELECT * FROM people WHERE name = 'David';

結果

Seq Scan on people  (cost=0.00..1887.08 rows=1050 width=22) (actual time=0.009..6.824 rows=1039 loops=1)Filter: (age = 18)Rows Removed by Filter: 98967
Planning Time: 0.072 ms
Execution Time: 6.857 ms----------------------------------------------------------------
Seq Scan on people  (cost=0.00..1887.08 rows=10204 width=22) (actual time=0.014..6.997 rows=10041 loops=1)Filter: ((name)::text = 'David'::text)Rows Removed by Filter: 89965
Planning Time: 0.057 ms
Execution Time: 7.207 ms

全表掃描,沒有走索引

總結

總的來說,Postgres 數據庫聯合索引生效條件遵循最左匹配原則。

在本例中,也就是說 city字段存在于 where條件的后面,才能高效的使用索引,如果沒有 city字段,可能也會命中索引,但是是不高效的,當三個聯合索引字段都存在時,這時是最高效的查詢語句。

另外,查詢字段在 WHERE 條件后面的順序是不妨礙索引是否命中的,PG 優化器會識別優化。

你對 Postgre 數據庫的聯合索引有了解嗎?你是否知道何種情況下 PG 數據庫會高效的命中索引,可以留下你的評論,我們一起討論。

如有錯誤,請指正~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81490.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81490.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81490.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot項目里面發起http請求的幾種方法

在Spring Boot項目中發起HTTP請求的方法 在Spring Boot項目中,有幾種常用的方式可以發起HTTP請求,以下是主要的幾種方法: 1. 使用RestTemplate (Spring 5之前的主流方式) // 需要先注入RestTemplate Autowired private RestTemplate restT…

《Python星球日記》 第90天:微調的概念以及如何微調大模型?

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 目錄 一、微調原理1. 什么是大模型微調?2. 為什么需要微調?3. 微調的基本流程4. 微調策略分類二、LoRA(Low-Rank Adaptation)技術詳解1. LoRA的核…

機器學習-人與機器生數據的區分模型測試 - 模型融合與檢驗

模型融合 # 先用普通Pipeline訓練 from sklearn.pipeline import Pipeline#from sklearn2pmml.pipeline import PMMLPipeline train_pipe Pipeline([(scaler, StandardScaler()),(ensemble, VotingClassifier(estimators[(rf, RandomForestClassifier(n_estimators200, max_de…

怎樣免費開發部署自己的網站?

要免費開發自己的網站,您可以根據自己的技術水平和需求選擇以下兩種主要方式: 零基礎用戶:建議使用如WordPress.com、Weebly、Strikingly等平臺,快速搭建網站。 有一定技術基礎的用戶:可選擇自行開發網站,…

調用百度云API機器翻譯

新建Python文件,叫 text_translator.py 輸入 import requests import jsonAPI_KEY "glYiYVF2dSc7EQ8n78VDRCpa" # 替換為自己的API Key SECRET_KEY "kUlhze8OQZ7xbVRp" # 替換為自己的Secret Keydef main():# 選擇翻譯方向while True:di…

OpenAI與微軟洽談新融資及IPO,Instagram因TikTok流失四成用戶

OpenAI與微軟洽談新融資及IPO 據悉,OpenAI 正與微軟洽談新融資及籌備 IPO,關鍵問題是微軟在 OpenAI 重組后的股權比例。微軟已投資超 130 億美元,雙方修訂 2019 年合同,微軟擬棄部分股權換新技術訪問權。OpenAI 上周放棄了有爭議轉…

git工具使用詳細教程-------命令行和TortoiseGit圖形化

下載 git下載地址:https://git-scm.com/downloads TortoiseGit(圖形化工具)下載地址:https://tortoisegit.org/download/ 認識git結構 工作區:存放代碼的地方 暫存區:臨時存儲,將工作區的代碼…

構建RAG混合開發---PythonAI+JavaEE+Vue.js前端的實踐

7GB顯存如何部署bf16精度的DeepSeek-R1 70B大模型?-CSDN博客 服務容錯治理框架resilience4j&sentinel基礎應用---微服務的限流/熔斷/降級解決方案-CSDN博客 conda管理python環境-CSDN博客 快速搭建對象存儲服務 - Minio,并解決臨時地址暴露ip、短…

【Java ee初階】jvm(3)

一、雙親委派機制(類加載機制中,最經常考到的問題) 類加載的第一個環節中,根據類的全限定類名(包名類名)找到對應的.class文件的過程。 JVM中進行類加載的操作,需要以來內部的模塊“類加載器”…

wps excel將表格輸出pdf時所有列在一張紙上

記錄:wps excel將表格輸出pdf時所有列在一張紙上 1,調整縮放比例,或選擇將所有列打印在一頁 2,將表格的所有鋪滿到這套虛線

分布式微服務系統架構第134集:筆記1運維服務器經驗,高并發,大數據量系統

加群聯系作者vx:xiaoda0423 倉庫地址:https://webvueblog.github.io/JavaPlusDoc/ https://1024bat.cn/ https://github.com/webVueBlog/fastapi_plus https://webvueblog.github.io/JavaPlusDoc/ ? 一、查看端口是否被占用的常用命令 1?? lsof 命令&…

IS-IS 中間系統到中間系統

前言: 中間系統到中間系統IS-IS(Intermediate System to Intermediate System)屬于內部網關協議IGP(Interior Gateway Protocol),用于自治系統內部 IS-IS也是一種鏈路狀態協議,使用最短路徑優先…

前端安全:XSS、CSRF 防御與最佳實踐

引言 隨著互聯網應用的普及,前端安全問題日益凸顯。作為開發者,了解并防范常見的安全威脅至關重要。本文將深入探討兩種最常見的前端安全威脅:跨站腳本攻擊(XSS)和跨站請求偽造(CSRF)&#xff…

uniapp 彈窗封裝(上、下、左、右、中五個方位)

無腦復制即可&#xff01;&#xff01;&#xff01; <template><view><viewv-if"mask"class"tui-drawer-mask":class"{ tui-drawer-mask_show: visible }":style"{ zIndex: maskZIndex }"tap"handleMaskClick&qu…

Axure制作可視化大屏動態滾動列表教程

在可視化大屏設計中&#xff0c;動態滾動列表是一種常見且實用的展示方式&#xff0c;能夠有效地展示大量信息。本文將詳細介紹如何使用Axure制作一個動態滾動的列表展示模塊。 一、準備工作 打開Axure軟件&#xff1a;確保你已經安裝并打開了Axure RP軟件。創建新項目&#x…

零基礎玩轉Apache Superset可視化部署

根據官方Quick Start Guide&#xff0c;你可以按照以下步驟進行部署&#xff1a; 1. 確認環境2. 獲取代碼3. 獲取官方最新代碼4. 啟動服務5. 訪問Superset Web界面6. 接入數據源 前提條件&#xff1a; dockerdocker compose 1. 確認環境 安裝Docker和Docker Compose 確保你…

服務器數據恢復—XFS文件系統分區消失的數據恢復案例

服務器數據恢復環境&故障&#xff1a; 服務器上有一組由raid卡組建的raid5磁盤陣列。上層安裝linux才做系統&#xff0c;采用XFS文件系統&#xff0c;劃分了3個分區。 管理員將服務器的操作系統重裝后&#xff0c;發現服務器上的分區發生了改變&#xff1a;一個分區消失&am…

2025/5/18

繼續研究一下大佬的RAG項目。開始我的碎碎念。 RAG可以分成兩部分&#xff1a;一個是問答&#xff0c;一個是數據處理。 問答是人提問&#xff0c;然后查數據庫&#xff0c;把查的東西用大模型組織成人話&#xff0c;回答人的提問。 數據處理是把當下知識庫里的東西&#xf…

在 Vue 中插入 B 站視頻

前言 在 Vue 項目中&#xff0c;有時我們需要嵌入 B 站視頻來豐富頁面內容&#xff0c;為用戶提供更直觀的信息展示。本文將詳細介紹在 Vue 中插入 B 站視頻的多種方法。 使用<iframe>標簽直接嵌入,<iframe>標簽是一種簡單直接的方式&#xff0c;可將 B 站視頻嵌…

OpenCv高階(八)——攝像頭調用、攝像頭OCR

文章目錄 前言一、攝像頭調用通用方法1、導入必要的庫2、創建攝像頭接口 二、攝像頭OCR1.引入庫2、定義函數&#xff08;1&#xff09;定義顯示opencv顯示函數&#xff08;2&#xff09;保持寬高比的縮放函數&#xff08;3&#xff09;坐標點排序函數&#xff08;4&#xff09;…