Postgresql: Подходящая многостолбцовая индексация для (отметка времени, строка) - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть таблица, в которой есть поле метки времени (в формате гггг-мм-дд ЧЧ: мм: сс.SSS ) (метка времени без часового пояса) и неуникальное поле (формат строки) .

Рассмотрим пример:
Предположим, что это таблица Пользователь (userId, userType ,ifiedOn) . userType - это неуникальный ключ, а изменение - это метка времени без часового пояса.

Таблица пользователей обновляется по некоторым приемлемым критериям по другим заданиям с интервалом 20–40 минут.

userType может иметь максимальное 200 различное значение , в то время как Таблица пользователя содержит миллионы данных .

Какой тип индексации мне следует использовать?

В настоящее время я пытаюсь

CREATE INDEX user_modifiedOn_userType_index on user USING btree(modifiedOn,userType);

Примечание :
Я помещаю промежуток времени между этими значениями, такими как «04-APR-18 07:44:21» и «06 -APR-18 07:44:21».
В настоящее время использование Postgresql версии 9.6 позже будет изменено на 10,3

Но у меня есть сомнения :

1) Насколько важен порядок столбцов в многоколоночной индексации?

Мысль: ModifiedOn будет иметь миллионы различных значений, поэтому он должен стоять первым, в то время как userType вряд ли имеет 200 различных значений.

2) Возможно ли индексирование по метке времени до часа или минуты? Если это возможно, то насколько это повлияет на производительность.

1 Ответ

0 голосов
/ 27 апреля 2018

TL; DR: В свете вашего наиболее частого запроса вы должны индексировать (user_type, modifiedon). Если вы опустите первый столбец, индекс будет неоптимальным, но все же полезным.

Подумайте, как организованы данные в индексе: по сути, это отсортированный список, упорядоченный сначала по первому столбцу индекса, а затем - ndash; в пределах каждой группы равных значений первого столбца & ndash; по второму столбцу индекса.

Так что если вы индексируете по (modifiedon, usertype), индекс будет выглядеть примерно так:

 modifiedon |  usertype
------------+-------------
 2018-01-01 | basicuser
 2018-01-01 | normaluser
 2018-01-01 | superuser
 2018-01-01 | .........
 2018-01-02 | normaluser
 2018-01-02 | .........
 .......... | .........
 2018-04-29 | basicuser
 2018-04-29 | normaluser
 2018-04-29 | xpertuser

Сканирование индекса можно использовать только в том случае, если искомые данные образуют непрерывный блок записей в индексе.

Теперь, если ваш запрос

SELECT * FROM user WHERE modifiedon BETWEEN $1 AND $2 AND usertype = $3;

индекс можно использовать для первых условий, поскольку записи для modifiedon между двумя датами образуют непрерывный блок записей индекса. Однако индекс не может использоваться для второго условия, поскольку записи индекса для определенного usertype не находятся рядом друг с другом в блоке, выбранном первым условием.

Однако, если у вас есть индекс на (usertype, modifiedon), он будет выглядеть так:

 usertype   | modifiedon
------------+-------------
 basicuser  | 2018-01-01
 basicuser  | 2018-01-02
 basicuser  | ..........
 basicuser  | 2018-04-29
 normaluser | 2018-01-01
 normaluser | 2018-01-02
 normaluser | ..........
 normaluser | 2018-04-29
 .......... | ..........
 xpertuser  | 2018-03-01
 xpertuser  | ..........
 xpertuser  | 2018-04-29

Очевидно, что записи, соответствующие запросу, образуют непрерывный блок записей в индексе, поэтому его можно использовать для всего условия .

Таким образом, этот комбинированный индекс является лучшим индексом для запроса.

Однако, может быть, очень мало usertype с. Тогда второе условие не очень избирательно, и нет большой выгоды от включения столбца usertype в индекс. На самом деле, это может быть вредно, поскольку увеличивает индекс, а это означает, что во время сканирования индекса потребуется больше работы, чтобы вы могли эффективно потерять его.

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