Индекс Postgresql для нескольких столбцов для BETWEEN и ORDER BY - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть большая таблица (100M записей) со следующей структурой.

  length   |          created_at
-----------+-------------------------------
 506225551 | 2018-12-29 02:08:34.116618
 133712971 | 2018-10-19 21:20:14.568936
 608443439 | 2018-12-14 03:22:55.141416
 927160571 | 2019-01-30 00:51:41.639126
 407033524 | 2018-11-16 21:26:41.523047
 506008096 | 2018-11-17 00:07:42.839919
 457719749 | 2018-11-12 02:32:53.116225
  • 0 < length < 1000000000
  • '2017-01-01' < created_at < '2019-02-01'
  • данные равномерно распределены дляlength и created_at.

Я хочу выполнить такие запросы

SELECT * FROM tbl WHERE length BETWEEN 2000000 and 3000000 ORDER BY  created_at DESC

Есть 100K результатов между 2000000 и 3000000, поэтому я хочу использовать индекс для выбораи для заказа.

Я попробовал эти подходы

1.Простой индекс BTREE

create index on tbl(length);

Это хорошо работает для короткого диапазона для length, но я не могу использовать этот индекс для упорядочения записи.

2.Многоколонный индекс BTREE

 create index on tbl(length, created_at);

Этот индекс я могу использовать только для таких запросов, как этот

 SELECT * FROM tbl WHERE length = 2000000 ORDER BY  created_at DESC

3.Индекс GIST с расширением btree_gist.Я ожидаю, что этот индекс должен работать.

create index on tbl using gist(length, created_at);   

Но это не так.Я не могу использовать этот индекс даже для простого запроса, подобного этому.

test=# explain analyze select * from gist_test where a = 345 order by c desc;

                                                                QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=25706.37..25730.36 rows=9597 width=12) (actual time=4.839..5.568 rows=10000 loops=1)
   Sort Key: c DESC
   Sort Method: quicksort  Memory: 853kB
   ->  Bitmap Heap Scan on gist_test  (cost=370.79..25071.60 rows=9597 width=12) (actual time=1.402..2.869 rows=10000 loops=1)
         Recheck Cond: (a = 345)
         Heap Blocks: exact=152
         ->  Bitmap Index Scan on gist_test_a_b_c_idx  (cost=0.00..368.39 rows=9597 width=0) (actual time=1.384..1.384 rows=10000 loops=1)
               Index Cond: (a = 345)
 Planning time: 0.119 ms
 Execution time: 6.271 ms

Я могу использовать этот индекс только как простой BTREE для одного столбца.

Итак, как я могу решить эту проблему?

Может, есть базы данных noSQL, которые могут обрабатывать запросы такого типа?

1 Ответ

0 голосов
/ 02 февраля 2019

Я не думаю, что это возможно (по крайней мере, в vanilla postgresql, я не знаю расширения, которое могло бы помочь в этом).Этап сортировки записей может быть пропущен только потому, что индексы уже производят отсортированные записи.
Однако:

  1. Как упоминалось в doc , могут использоваться только индексы B-дерева.для сортировки (что имеет смысл, она реализована с использованием дерева поиска).
  2. Ваш where и ваш order by несовместимы для индекса B-дерева:
    • Из-за наличия обоихпредложения, вам нужно поместить 2 столбца в индекс (A, B)
    • Данные в индексе отсортированы по (A, B), поэтому они также отсортированы по A (поэтому postgresql может индексироватьсканировать таблицу быстро, когда where включен только A), но, как следствие, она не отсортирована по B в индексе (она сортируется по B только в каждомподмножество, где A является константой, но не по всей таблице).
    • Как вы, наверное, уже знаете, наличие индекса только для B будет мало чем помогать из-за where.

Приведенный пример №2 показывает postgresqlхорошо оптимизирован для случая, когда вы фильтруете по одному значению A.

Если сортировка по 2 столбцам (A, B) недопустима, то, боюсь, вы не должны ожидать большего, чемэто.

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