Postgresql создает индекс функции по динамическим значениям - PullRequest
0 голосов

У меня такой запрос

select r.timestamp, r,value
   from result_table r
  where timestamp > ( NOW() - INTERVAL '120 hour' )
    and r.id%10=1`

где id - автоинкрементный первичный ключ.

Вместо 120 и 10 можно использовать любой другой номер (определяется пользователем в зависимости от его потребностей). По сути, пользователь хочет данные за некоторый интервал времени с некоторым прореживанием.

Очевидно, что он работает слишком медленно на большом количестве данных. Какими здесь должны быть индексы?

1 Ответ

0 голосов
/ 01 мая 2018

PostgreSQL поддерживает выражения SQL или индексы функций

  where
    timestamp > ( NOW() - INTERVAL '120 hour' )
    and r.id % 10 = 1

Нужен индекс (timestamp, (id % 10)) для увеличения производительности.

Запрос

CREATE INDEX
 timestamp__idmod10
ON 
 result_table
(timestamp, (id % 10))

см. Демонстрации

с индексом http://sqlfiddle.com/#!17/8e63b/6
без индекса http://sqlfiddle.com/#!17/9be99/3

Изменено из-за комментария

Спасибо, Раймонд, однако (id% 10) не так хорош, так как вместо 10 может быть любым другим числом. 9, 11, 100, 1 и т. Д.

Другой подход использует generate_series() и предоставленную таблицу для создания списка идентификаторов, соответствующего% number = 1.
И используйте этот набор результатов с предложением IN.

p.s этот оператор предполагает использование столбца id с SERIAL и таблицей, равной или меньшей 1 миллиона записей. Также имейте в виду, что функция generate_series() занимает некоторое время.

SQL-оператор

 SELECT 
   numbers.number FROM (  
      SELECT
        generate_series(1, 1000000) as number
      ) AS numbers 
    WHERE
      numbers.number % number = 1

Тогда вы можете использовать индекс

CREATE INDEX timestamp_id ON result_table(timestamp, id);

И запрос

SELECT 
 *
FROM 
 result_table 
WHERE
   timestamp > ( NOW() - INTERVAL '120 hour' ) 
 AND
   id IN (

     SELECT 
       numbers.number FROM (  
          SELECT
            generate_series(1, 1000000) as number
          ) AS numbers 
        WHERE
          numbers.number % 10 = 1

   )

см. Демонстрацию http://sqlfiddle.com/#!17/5013c0/6 с примерами данных.

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