EDIT: К последнему праву для текущего состоянияpostgresql, получить список предметов с ближайшей точкой, где условие истинно
Здравствуйте!
У меня есть таблица с метеостанций
станции:
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 |
и другой locations_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, ветер ..) ближайшей точку, где эти пары не нуль, а не 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)
, который довольно быстро ~ 150мс и только индекс getti нг используется 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 не используется, если в предложении «n.station_id IN» содержится более 5 значений?
Есть ли способ выбрать все необходимые значения в одном запросе в разумные сроки?
Спасибо за чтение :)
PS: Postgres 9.5 с PostGIS включен
EDIT: на самом деле КТР должен выглядеть так, чтобы получить правильную точку для заказа ..но то, что сторона здесь
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
)
EDIT: После 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
который быстро ~ 200мс даже с большим количеством станций =>https://explain.depesz.com/s/kA8
Отметьте это сообщение как ответ в течение нескольких дней.
Оптимизация по-прежнему приветствуется.
Примечание: определение вашей таблицы noaa не содержит столбцов 'dt' и' station_id'. Пожалуйста, добавьте определения таблицы * real * таблицы (ов) к вашему вопросу. – joop