Принудительное сканирование индекса для сравнения нескольких столбцов - PullRequest
1 голос
/ 10 апреля 2019

Я знаю, что внутренним индексом является B-дерево или аналогичная древовидная структура.Предположим, что индекс построен для 3 столбцов (a,b,c), я хочу, чтобы Postgres:

  1. нашел ключ [a = 10, b = 20, c = 30] в этом B-дереве,
  2. сканировать следующие 10 записей и возвращать их.

Если индекс имеет только один столбец, решение очевидно:

select * from table1
where a >= 10
order by a limit 10

Но если столбцов больше, решение становится намногоболее сложный.Для 2 столбцов:

select * from table1
where a > 10 or (a = 10 and b >= 20)
order by a, b limit 10

3 столбца:

select * from table1
where a > 10 or (a = 10 and (b > 20 or b = 20 and c >= 30))
order by a, b, c limit 10

Обратите внимание, что запрос:

select * from table1
where a >= 10 and b >= 20 and c >= 30
order by a, b, c limit 10

является неверным , поскольку он будетнапример, отфильтровать [a = 11, b = 10, c = 1].

Как я могу сообщить Postgres, что я хочу эту операцию?

И могу ли я быть уверен, что даже для этих сложных запросов для 2+ столбцов оптимизатор всегда поймет, что он должен выполнить сканирование диапазона?Почему?

1 Ответ

3 голосов
/ 10 апреля 2019

Используйте ROW значения для сравнения:

SELECT *
FROM   table1
WHERE  (a,b,c) >= (10, 20, 30)
ORDER  BY a,b,c
LIMIT  10;

(Использование >= для соответствия вашему коду, хотя ваше описание предлагает >. Либо работает.)

(a,b,c) является кратким обозначением для ROW(a,b,c), действительно.

И да, Postgres понимает, что для этого он может использовать соответствующий многоколонный индекс B-дерева (в отличие от некоторых других СУБД - или так, как я слышал).

«Соответствие» означает, что все выражения индекса, их последовательность и связанный с ними порядок (ASC | DESC) одинаковы - или порядок сортировки всей строки индекса полностью инвертирован, так что Postgres может сканировать указатель назад почти с той же скоростью.
Для приведенного примера эти индексы соответствуют:

(a ASC, b ASC, c ASC)
(a DESC, b DESC, c DESC)

Но они делают не :

(a ASC, b DESC, c ASC)
(a ASC, c ASC, b ASC)

Оптимизация запросов по диапазону временных отметок (два столбца)

Связано с более подробным объяснением:

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