簡體   English   中英

Postgres在兩個相同表之間的左連接非常慢

[英]Postgres Left join between two identical tables very slow

嗨,我在理解性能問題時遇到了麻煩。 我有兩個相同的結構化表sensor_values和sensor_values_cleaned結構為

CREATE TABLE sensor_values
(
  ts timestamp with time zone NOT NULL,
  value double precision NOT NULL DEFAULT 'NaN'::real,
  sensor_id integer NOT NULL,
  CONSTRAINT sensor_values_sensor_id_fkey FOREIGN KEY (sensor_id)
      REFERENCES sensors (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT timestamp_sensor_index UNIQUE (ts, sensor_id)
)

兩個表的ts和sensor_id字段都有索引。 (這些表實際上是按年季度划分的許多分區表)

問題查詢是

SELECT MIN(s1.ts)::timestamptz(0) AS min_time, AVG(s1.value), AVG(s2.value)
FROM sensor_values s1 LEFT JOIN sensor_values_cleaned s2 USING (sensor_id,ts)
 WHERE s1.ts::timestamptz >= '2011-02-25T20:25:07.192132+00:00'::timestamptz AND s1.ts::timestamptz <= '2012-12-31T23:59:59.999999'::timestamp 
 AND s1.sensor_id IN (904 ) GROUP BY s1.ts::timestamptz ORDER BY 1 DESC

這個想法是獲取每個sensor_id的原始數據和清除的數據。 我的原始查詢針對此數據進行了樞軸處理,但由於該部分運行緩慢,因此已將其刪除。

sensor_id 904 has 88000 rows in sensor_values and 0 in sensor_values_cleaned

多次運行后,此查詢大約需要1300毫秒。 問題是當我添加到IN子句時

SELECT MIN(s1.ts)::timestamptz(0) AS min_time, AVG(s1.value), AVG(s2.value)
FROM sensor_values s1 LEFT JOIN sensor_values_cleaned s2 USING (sensor_id,ts)
 WHERE s1.ts::timestamptz >= '2011-02-25T20:25:07.192132+00:00'::timestamptz AND s1.ts::timestamptz <= '2012-12-31T23:59:59.999999'::timestamp 
 AND s1.sensor_id IN (904, 967 ) GROUP BY s1.ts::timestamptz ORDER BY 1 DESC

緩存需要15秒。 第一次運行需要40個!

sensor id 967 has 69600 rows in sensor_values and 0 in sensor_values_cleaned.

我已經進行了真空分析

有人知道這個問題或有建議嗎?

謝謝

我的查詢分析在

https://dl.dropboxusercontent.com/u/189370/query_analyze.txt

在以下情況下的最后一個強制轉換( ::timestamp )可能剝奪了計划者限制表搜索的機會。

WHERE 
    s1.ts::timestamptz >= '2011-02-25T20:25:07.192132+00:00'::timestamptz AND  
    s1.ts::timestamptz <= '2012-12-31T23:59:59.999999'::timestamp 

嘗試將其更改為

s1.ts >= '2011-02-25t20:25:07.192132+00:00'::timestamptz and 
s1.ts < '2013-01-01'::timestamptz

然后比較並發布新計划。 同樣也不需要ts因為它已經是timestamp with time zone

更新資料

這不能解釋行為,但可以使其更快:

select
    sensor_id,
    min(ts)::timestamptz(0) as min_time,
    avg(s1.value),
    avg(s2.value)
from
    (
        select ts, "value", sensor_id
        from sensor_values
        where
            ts >= '2011-02-25t20:25:07.192132+00:00'::timestamptz and ts < '2013-01-01'::timestamptz
            and sensor_id in (904)
    ) s1
    left join (
        select ts, "value", sensor_id
        from sensor_values_cleaned
        where
            ts >= '2011-02-25t20:25:07.192132+00:00'::timestamptz and ts < '2013-01-01'::timestamptz
            and sensor_id in (904)
    ) s2 using (sensor_id,ts)
group by sensor_id
order by 1 desc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM