Можно ли изменить порядок выполнения индекса в postgresql? - PullRequest
0 голосов
/ 17 апреля 2020

Я создаю тестовую таблицу в своем postgresql дБ, чтобы попытаться описать вопрос. Имя таблицы: тестовые столбцы: id (varchar, uuid), create_at (метка времени)

Я вставляю некоторые ложные данные в таблицу.

postgres=# select count(1) from test;
  count
---------
 1200001
(1 row)

Вот запрос A:

postgres=# explain select id from test
postgres-# where id > '67542377-b900-4084-b619-bae9448a73b5'
postgres-# and created_at >= '2020-04-17 08:23:22.229' and created_at < '2020-04-17 08:24:26.474'
postgres-# order by id limit 1000;
                                                                                  QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=2335.83..2338.33 rows=1000 width=37)
   ->  Sort  (cost=2335.83..2381.98 rows=18460 width=37)
         Sort Key: id
         ->  Index Scan using index_create_at on test  (cost=0.43..1323.69 rows=18460 width=37)
               Index Cond: ((created_at >= '2020-04-17 08:23:22.229'::timestamp without time zone) AND (created_at < '2020-04-17 08:24:26.474'::timestamp without time zone))
               Filter: ((id)::text > '67542377-b900-4084-b619-bae9448a73b5'::text)
(6 rows)

Тогда запрос B:

postgres=# explain select id from test
postgres-# where id > '67542377-b900-4084-b619-bae9448a73b5'
postgres-# and created_at >= '2020-04-17 08:23:22.229' and created_at < '2020-04-17 08:40:26.474'
postgres-# order by id limit 1000;
                                                                             QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.43..122.60 rows=1000 width=37)
   ->  Index Scan using test_pkey on test  (cost=0.43..87966.38 rows=720001 width=37)
         Index Cond: ((id)::text > '67542377-b900-4084-b619-bae9448a73b5'::text)
         Filter: ((created_at >= '2020-04-17 08:23:22.229'::timestamp without time zone) AND (created_at < '2020-04-17 08:40:26.474'::timestamp without time zone))
(4 rows)

Я заметил, что план выполнения отличается из-за разных значений созданного_произведения. В этом примере оптимизатор postgres, кажется, принимает правильное решение (это низкая стоимость).

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

Я попытался написать запрос B различными способами, чтобы попытаться изменить порядок индекса выполнения, но не смог. план не меняется.

postgres=# explain select id from
postgres-# (select id from test where created_at >= '2020-04-17 08:23:22.229' and created_at < '2020-04-17 08:40:26.474') t1
postgres-# where id > '67542377-b900-4084-b619-bae9448a73b5'
postgres-# order by id limit 1000;
                                                                             QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.43..122.60 rows=1000 width=37)
   ->  Index Scan using test_pkey on test  (cost=0.43..87966.38 rows=720001 width=37)
         Index Cond: ((id)::text > '67542377-b900-4084-b619-bae9448a73b5'::text)
         Filter: ((created_at >= '2020-04-17 08:23:22.229'::timestamp without time zone) AND (created_at < '2020-04-17 08:40:26.474'::timestamp without time zone))
(4 rows)

Ниже приведен план запроса из производства:

explain select id from t_test_log
where id > '51666ee5ca624653b745a11635c436af'
and created_at >= '2019-02-02T00:00.000Z' and created_at < '2019-02-02T01:00.000Z'
order by id limit 1000;
                                                                              QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=228.45..230.93 rows=991 width=33)
   ->  Sort  (cost=228.45..230.93 rows=991 width=33)
         Sort Key: id
         ->  Index Scan using idx_test_log_create_at on t_test_log  (cost=0.57..179.13 rows=991 width=33)
               Index Cond: ((created_at >= '2019-02-02 00:00:00'::timestamp without time zone) AND (created_at < '2019-02-02 00:01:00'::timestamp without time zone))
               Filter: ((id)::text > '51666ee5ca624653b745a11635c436af'::text)
(6 rows)
explain select id from t_test_log
where id > '51666ee5ca624653b745a11635c436af'
and created_at >= '2019-02-02T00:00.000Z' and created_at < '2019-02-03T01:00.000Z'
order by id limit 1000;
                                                                         QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.70..39262.61 rows=1000 width=33)
   ->  Index Scan using pk_test_log_main on t_test_log  (cost=0.70..52354159.88 rows=1333459 width=33)
         Index Cond: ((id)::text > '51666ee5ca624653b745a11635c436af'::text)
         Filter: ((created_at >= '2019-02-02 00:00:00'::timestamp without time zone) AND (created_at < '2019-02-03 00:01:00'::timestamp without time zone))
(4 rows)

Так что можно изменить план запроса B, чтобы принудительно использовать его план такой же, как запрос A?

1 Ответ

0 голосов
/ 17 апреля 2020

Как правило, вы не можете заставить запрос использовать указанный индекс c, но вы можете повлиять на планировщик запросов с лучшей статистикой, переписав запрос или с некоторыми параметрами.

См. Связанные обсуждения: Как заставить Postgres использовать определенный индекс? Postgres оптимизация запросов (принудительное сканирование индекса)

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