编辑:跳至上次编辑当前状态
你好!
我有一张带气象站的桌子
站:
id,
point, (geometry(Point,4326))
ctry (country code)
包含天气数据的表格:
NOAA:
id | integer | not null default nextval('noaa_id_seq'::regclass)
usaf_wban | text |
station_id | integer |
usaf | integer |
wban | integer |
dt | timestamp without time zone | not null
point | geometry(Point,4326) |
air_temp | double precision |
dew_point | double precision |
relative_humidity | double precision |
sea_level_pressure | double precision |
pressure | double precision |
wind | double precision |
cloudiness | double precision |
ghi | double precision |
和另一个location_location,我得到了点
我已经用索引进行了很多实验,noaa表上的当前索引是:
Indexes:
"noaa_pkey" PRIMARY KEY, btree (id)
"noaa_dt_trunc" btree (date_trunc('hour'::text, dt))
"noaa_point" gist (point)
"noaa_station_ids" btree (station_id)
现在我想为每个参数选择(air_temp,wind ..) 此参数不是空的最近点而不是9999
此时我使用了5个单独的查询:
with postal_station AS (
SELECT id as station_id, s.point FROM stations s WHERE s.ctry = 'AU'
ORDER BY s.point <-> (
SELECT point FROM locations_location l
WHERE l.postal_code = '9201' AND l.country_code = 'AT'
LIMIT 1
)
LIMIT 5
)
SELECT
DISTINCT ON (date_trunc('hour', dt))
date_trunc('hour', dt) as dt,
cloudiness
FROM
noaa n
WHERE
dt BETWEEN '2010-01-01'::timestamp AND '2015-01-01'::timestamp
AND
NOT cloudiness = 9999
AND
NOT cloudiness is null
AND
n.station_id IN (SELECT station_id FROM postal_station)
ORDER BY dt, point <-> ( SELECT point FROM postal_station LIMIT 1 )
非常快〜150ms,唯一使用的索引是noaa_station_ids
但是目前我将station_ids的限制增加到5:
with postal_station AS (
SELECT id as station_id, s.point FROM stations s WHERE s.ctry = 'AU'
ORDER BY s.point <-> (
SELECT point FROM locations_location l
WHERE l.postal_code = '9201' AND l.country_code = 'AT'
LIMIT 1
)
LIMIT 6
)
SELECT
DISTINCT ON (date_trunc('hour', dt))
date_trunc('hour', dt) as dt,
air_temp
FROM
noaa n
WHERE
dt BETWEEN '2010-01-01'::timestamp AND '2015-01-01'::timestamp
AND
NOT air_temp = 9999
AND
NOT air_temp is null
AND
n.station_id IN (SELECT station_id FROM postal_station)
ORDER BY dt, point <-> ( SELECT point FROM postal_station LIMIT 1 )
https://explain.depesz.com/s/9n2M
索引noaa_station_ids不再使用,查询大概需要~2429ms
所以这是我的问题:
为什么没有使用索引noaa_station_ids如果&#34; n.station_id IN&#34;子句包含5个以上的值?
有没有办法在合理的时间内在一个查询中选择所有需要的值?
感谢您阅读:)
PS:启用了postgis的Postgres 9.5
编辑:实际上cte应该看起来像这样才能得到正确的订购点..但这是一个侧面的事情with postal_point AS (
SELECT point FROM locations_location l
WHERE l.postal_code = '9201' AND l.country_code = 'AT'
LIMIT 1
),
postal_station AS (
SELECT id as station_id, s.point FROM stations s WHERE s.ctry = 'AU'
ORDER BY s.point <-> ( SELECT point FROM postal_point )
LIMIT 5
)
编辑:在freenode上的joinen #postgresql之后,RhodiumToad帮我构建了这个查询
with postal_station AS (
select
s1.*
from (
select point from locations_location l where l.postal_code = '9201' AND l.country_code = 'AT' limit 1
) l0,
lateral (
select s.id, rank() over (order by s.point <-> l0.point)
from
stations s
where
s.ctry = 'AU'
order by s.point <-> l0.point limit 20) s1
)
SELECT
DISTINCT ON (date_trunc('hour', dt))
date_trunc('hour', dt) as dt,
air_temp
FROM
noaa n
JOIN
postal_station p
ON
p.id = n.station_id
WHERE
dt BETWEEN '2010-01-01'::timestamp AND '2015-01-01'::timestamp
AND
NOT air_temp = 9999
AND
NOT air_temp is null
ORDER BY dt, p.rank
哪个快〜200ms即使有更多的站=&gt; https://explain.depesz.com/s/kA8
我会在几天内将这篇文章标记为已回答。
仍然欢迎优化。
答案 0 :(得分:0)
1) Why is the index noaa_station_ids not used if the "n.station_id IN" clause contains more then 5 values ?
2) Is there a way to select all needed values in one query in reasonable time ?
1)在将cpu_tuple_cost增加到0.1之后,索引也被用于更多的站点,但查询仍然越来越慢,站点数量越来越多
2)atm我使用5个查询并立即发送它们以获取所有需要的数据,以及上次编辑中的查询查询时间正常。
查询:
关键是在cte中对电台进行排名,然后加入cte。 这样排序要快得多。