У меня есть большая таблица идентификаторов, даты, значений. У него около 30 000 идентификаторов, а даты - 20 лет неполных дней недели (пропущенные праздники и некоторые случайные данные). Для данного идентификатора и списка дат, я ищу значение, которое является самым последним для этих дат. У меня есть код, который работает, но довольно медленный, и я подумал, можно ли его существенно улучшить.
Следующий код устанавливает фиктивную версию проблемы. Вместо дней недели я просто производил данные за каждый второй день. Прошу прощения за мой плохой код, я не уроженец Postgresql.
CREATE TABLE public.testtable
(
myid character(8) COLLATE pg_catalog."default" NOT NULL,
mydate date NOT NULL,
myvalue double precision,
CONSTRAINT testtable_pkey PRIMARY KEY (myid, mydate)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
CREATE UNIQUE INDEX testtable_index
ON public.testtable USING btree
(myid COLLATE pg_catalog."default", mydate)
TABLESPACE pg_default;
ALTER TABLE public.testtable
CLUSTER ON testtable_index;
-- insert some test data
DO $$
BEGIN
FOR counter IN 1..100 LOOP
insert into testtable
SELECT array_to_string(ARRAY(SELECT chr((65 + round(random() * 25)) :: integer) FROM generate_series(1,8)), '') as myid, dates.mydate, dates.mydate - '1998-12-31' as myvalue
from (SELECT date_trunc('day', dd)::date as mydate
FROM generate_series
( '1999-01-01'::date
, '2019-01-01'::date
, '2 days'::interval) dd) as dates;
END LOOP;
END; $$
Далее я получаю минимальный идентификатор и помещаю его в мой запрос выбора. На самом деле я буду вводить разные идентификаторы здесь, чтобы получить серию для этого идентификатора.
select distinct on (x.search_dates)
x.search_dates, t1.myid, t1.mydate, t1.myvalue
from (SELECT date_trunc('day', dd)::date as search_dates
FROM generate_series
( '2008-01-01'::date
, '2018-01-01'::date
, '1 week'::interval) dd) as x
left join public.testtable t1 on t1.mydate <= x.search_dates and t1.mydate >= x.search_dates - INTERVAL '7 days'
where t1.myid = (select min(myid) from testtable) -- replace with specific id
order by x.search_dates, t1.mydate desc
Это выдает результат, который я получаю, и сама по себе скорость в порядке, но я запускаю этот запрос для всех 30 000 идентификаторов последовательно, и это происходит в часах.
Основной вопрос заключается в том, существует ли какой-либо лучший способ воздействия на индексы в этой ситуации, чтобы ускорить это? Когда я запускаю EXPLAIN для этого запроса, появляется вложенный цикл, который обрабатывает более 400 000 строк (в примере), и я не уверен, что это генерирует.
Я предполагаю, что более широкий вопрос заключается в том, означает ли тот факт, что я ищу неточные совпадения, это всегда будет медленно? Если это так, есть ли лучший метод для базы данных / хранилища данных, который бы лучше подходил данным временного ряда? Конечный пункт назначения данных - R, поэтому я довольно открыт для других методов.
Спасибо всем.