Postgresql поиск ближайших дат - повышение скорости при большом поиске нескольких дат - PullRequest
0 голосов
/ 16 января 2019

У меня есть большая таблица идентификаторов, даты, значений. У него около 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, поэтому я довольно открыт для других методов.

Спасибо всем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...