PostgresSQL 多索引調整
我有一個包含這些列的表:id、uuid、customer_id、building、dept、values
我在這些列上有一個組合索引:
building, dept
.如果我執行這個查詢:
select count(*) from my_table where building = 666 and dept = 'my_dept'
,它需要 400 毫秒並且有 25 行如果我執行此查詢:
select count(*) from my_table where building = 666 and dept = 'my_dept' and customer_id = 1
,則需要 4 分鐘。它總是返回 25 行這意味著所有 25 行都屬於客戶 1。該表包含約 2000 萬行
我知道我可以解決添加
customer_id
到多列索引中的問題,但為什麼在第二種情況下這麼慢?即使缺少 customer_id,它是否應該從多列索引中受益?我預計它會慢一點,但不是 4 分鐘。任何的想法?
不同之處在於第一個查詢可以對兩列索引使用僅索引掃描,因為不需要其他列。第二個查詢還必須檢查
customer_id
列,因此它必須獲取表行。如果您想要對第二個查詢進行僅索引掃描,請按如下方式創建索引:
CREATE INDEX ON my_table (building, dept) INCLUDE (customer_id);
看起來沒有
customer_id
作為列building_dept
將成為您的問題。對於您的第一個查詢,優化器知道它可以簡單地計算從
building_dept
索引直接返回的所有行,而無需在其他地方查找其他數據。但是,一旦添加了額外的 where 子句,您就可以讓優化器做出決定。要查找帶有 的行
customer_id
,它可以做兩件事之一。
- 繼續使用
building_dept
索引,然後customer_id
在主表中查找。- 使用
customer_uuid
然後在主表中查找building
和。dept
無論哪種情況,它現在都需要在兩個地方而不是一個地方查找數據,以返回您請求的數據。如果您沒有
customer_uuid
索引,優化器將不會做出該決定,並會選擇選項 1。但是,它仍會在兩個位置而不是 1 中查找數據。這仍然不是最佳的。Postgres 可以使用統計資訊估計將返回的行數或行數,並且使用這些,它認為更好的計劃是轉到
customer_id-uuid
索引然後在主表中查找building
,dept
而不是使用building_dept
索引並customer
在主表中查找。嘗試查看您的統計資訊,以查看 Postgres 認為您傳遞給查詢的值有多少行。同樣,嘗試獨立執行這三個 select 並查看每個返回多少行。
select count(*) from my_table where building = 666
select count(*) from my_table where dept = 'my_dept'
select count(*) from my_table where customer_id = 1
總而言之,您最好的選擇是添加
customer_id
到building_dept
索引中,看看這是否有助於第二個查詢。