Postgresql

PostgresSQL 多索引調整

  • March 7, 2022

我有一個包含這些列的表: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,它可以做兩件事之一。

  1. 繼續使用building_dept索引,然後customer_id在主表中查找。
  2. 使用customer_uuid然後在主表中查找building和。dept

無論哪種情況,它現在都需要在兩個地方而不是一個地方查找數據,以返回您請求的數據。如果您沒有customer_uuid索引,優化器將不會做出該決定,並會選擇選項 1。但是,它仍會在兩個位置而不是 1 中查找數據。這仍然不是最佳的。

Postgres 可以使用統計資訊估計將返回的行數或行數,並且使用這些,它認為更好的計劃是轉到customer_id-uuid索引然後在主表中查找buildingdept而不是使用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_idbuilding_dept索引中,看看這是否有助於第二個查詢。

引用自:https://dba.stackexchange.com/questions/308299