Postgresql

當我在 where 語句中再添加一個 id 時,為什麼我的查詢會掛起?

  • September 21, 2017

我有一個看起來像的查詢

select count(*)

FROM (joins)

WHERE customer_id in (select id from customer limit 117) AND ... (more statements)

它涉及具有數億條記錄的表,表大小約為 60GB,包括所有索引。117 的結果將是 1965 年的計數,118 的預期計數將是 1986 年。

限制為 117 時,語句會在幾百毫秒內返回。當我將限制設置為 118 時,查詢只是坐在那裡並且根本不返回。

這是使用 RDS Postgres 實例,並通過 IntelliJ 執行語句。我還閱讀了有關使用大型 WHERE IN 語句的性能不如通過臨時表加入 id 的性能,因此我編輯了語句以使用 WITH,但在 117 和 118 之間存在相同的掛起。

我假設我遇到了一些與硬體有關的約束/限制,而不是聲明,我只是不確定是什麼。

編輯:當我將WHERE子句更改WHERE customer_id between 1 and 1000為查詢時仍然非常快,並且 1 到 1000 之間的 id 沒有間隙。

從那以後,我也將我的 RDS 實例從中型更改為 XL,現在我可以從 128 限制,但 129 掛起。從監控來看,沒有什麼奇怪的。

您可能正在耗盡一些資源(足夠的資源設置?)並且 Postgres 開始換出到磁碟。和/或,更有可能的是,查詢計劃程序會根據您的成本設置(可能配置不充分)和表統計資訊(可能已過時)切換到不同的查詢計劃。

我不能更具體,資訊失去。

除了設置中的所有這些可能的問題,假設customer.id是一個唯一的列,這個具有JOIN替換的等效查詢IN (subquery)應該要快得多:

SELECT count(*)
FROM   (SELECT id FROM customer LIMIT 128) c  -- arbitrary rows! see below
JOIN   joins j ON j.customer_id = c.id        -- resolve "joins" properly
WHERE  -- ... (more expressions)

或者將子查詢放在 CTE 中。重要的一點是 join 而不是IN. 喜歡:

WITH cids AS (SELECT id FROM customer LIMIT 128)  -- arbitrary rows!
SELECT count(*)
FROM   cids c  
JOIN   ...

根據(joins)原始查詢中的內容調整連接子句。

另外,請注意,LIMIT如果不ORDER BY選擇任意行。因此,由於內部影響,子查詢 withLIMIT 128可以返回與 with 完全不同的 ID LIMIT 129(即使是相同的LIMIT),這可能導致完全不同的計數。那是你要的嗎?

有關的:

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