Postgresql

如何加快選擇不同的?

  • September 17, 2021

我對一些時間序列數據有一個簡單的選擇:

SELECT DISTINCT user_id
FROM events
WHERE project_id = 6
AND time > '2015-01-11 8:00:00'
AND time < '2015-02-10 8:00:00';

它需要112秒。這是查詢計劃:

http://explain.depesz.com/s/NTyA

我的應用程序必須執行許多不同的操作並像這樣計數。有沒有更快的方法來獲取這種數據?

你可能不想听到這個,但加快速度的最佳選擇SELECT DISTINCT避免 DISTINCT一開始。在許多情況下(不是全部!)可以通過更好的數據庫設計或更好的查詢來避免。

有時,GROUP BY更快,因為它採用不同的程式碼路徑。

您的特定情況下,您似乎無法擺脫DISTINCT(好吧,見下文)。但是,如果您有許多此類查詢,則可以使用特殊索引來支持查詢:

CREATE INDEX foo ON events (project_id, "time", user_id);

在 Postgres 11 或更高版本中,您可以使用實際的“覆蓋”索引,例如:

CREATE INDEX foo ON events (project_id, "time") INCLUDE (user_id);

user_id僅當您從中獲得僅索引掃描時,添加才有用。看:

將從您的查詢計劃中刪除昂貴的點陣圖堆掃描,這會消耗 90% 的查詢時間。

EXPLAIN顯示了 50 萬行中的 2,491 個不同的使用者。無論您做什麼,這都不會變得超快,但它可以更快。每個使用者大約有 200 行,在上面的索引上模擬索引跳過掃描可能會有所回報。範圍條件time很複雜,每個使用者 200 行仍然是一個適中的數字。所以不確定。看:

無論哪種方式,如果您的查詢中的時間間隔始終相同,那麼每次MATERIALIZED VIEW折疊都會有很長的路要走。但是,在不同的時間間隔內沒有機會。也許您至少可以每小時或其他一些最小時間單位折疊使用者,這將購買足夠的性能來保證相當大的成本。可以與任一查詢樣式結合使用。user_id``(project_id, <fixed time interval>)

Nitpick:

很可能,謂詞"time"真的應該是:

AND "time" >**=** '2015-01-11 8:00:00'
AND "time" <  '2015-02-10 8:00:00';

旁白:

不要time用作標識符。它是標準 SQL 中的保留字,也是 Postgres 中的基本類型。

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