Медленное время выполнения запроса postgres с индексом из нескольких столбцов - PullRequest
2 голосов
/ 13 мая 2019

Мы работаем с базой данных PostgresSql 9.6.11 в Amazon RDS.Время выполнения одного из запросов составляет 6633,645 мс.Это кажется очень медленным.Какие изменения я могу сделать, чтобы улучшить время выполнения этого запроса.

Запрос выбирает 3 столбца, в которых данные соответствуют 6 столбцам.

select
    platform,
    publisher_platform,
    adset_id
FROM "adsets"
WHERE
    (("adsets"."account_id" IN ('1595321963838425', '1320001405', 'urn:li:sponsoredAccount:507697540')) AND
    ("adsets"."date" >= '2019-05-06 00:00:00.000000+0000') AND ("adsets"."date" <= '2019-05-13 23:59:59.999999+0000'))
GROUP BY
    "adsets"."platform",
    "adsets"."publisher_platform",
    "adsets"."adset_id"
ORDER BY
    "adsets"."platform",
    "adsets"."publisher_platform",
    "adsets"."adset_id";

Запрос основан на таблице, называемой таблицей объявлений.В таблице есть следующие столбцы

account_id |текст
campaign_id |текст
adset_id |текст
имя |текст
дата |временная метка без часового пояса publisher_platform |text

и 15 других столбцов, представляющих собой смесь целых чисел и текстовых полей.

Мы добавили следующие индексы -

  1. "adsets_composite_unique_key" UNIQUE CONSTRAINT, btree(платформа, account_id, campaign_id, adset_id, date, publisher_platform)
  2. "adsets_account_id_date_idx" btree (account_id DESC, date DESC) CLUSTER
  3. "adsets_account_id_index" btree (account_id * 10 * 10 * 10 * 10 * 10 *) *"adsets_adset_id_index" ВТКЕЙ (adset_id)
  4. "adsets_campaign_id_index" ВТКЕЙ (campaign_id)
  5. "adsets_name_index" ВТКЕЙ (имя)
  6. "adsets_platform_platform_id_publisher_platform" ВТКЕЙ (account_id, платформа, publisher_platform,adset_id)
  7. "idx_account_date_adsets" btree (account_id, date)
  8. "platform_pub_index" btree (платформа, publisher_platform, adset_id).

Работа была выполнена в postgresустановлено 125MB

Объяснить (проанализировать) показывает

   Group  (cost=33447.55..33532.22 rows=8437 width=29) (actual time=6625.170..6633.062 rows=2807 loops=1)
   Group Key: platform, publisher_platform, adset_id
   ->  Sort  (cost=33447.55..33468.72 rows=8467 width=29) (actual time=6625.168..6629.271 rows=22331 loops=1)
         Sort Key: platform, publisher_platform, adset_id
         Sort Method: quicksort  Memory: 2513kB
         ->  Bitmap Heap Scan on adsets  (cost=433.63..32895.18 rows=8467 width=29) (actual time=40.003..6471.898 rows=22331 loops=1)
               Recheck Cond: ((account_id = ANY ('{1595321963838425,1320001405,urn:li:sponsoredAccount:507697540}'::text[])) AND (date >= '2019-05-06 00:00:00'::timestamp without time zone) AND (date <= '
2019-05-13 23:59:59.999999'::timestamp without time zone))
               Heap Blocks: exact=52907
               ->  Bitmap Index Scan on idx_account_date_adsets  (cost=0.00..431.51 rows=8467 width=0) (actual time=27.335..27.335 rows=75102 loops=1)
                     Index Cond: ((account_id = ANY ('{1595321963838425,1320001405,urn:li:sponsoredAccount:507697540}'::text[])) AND (date >= '2019-05-06 00:00:00'::timestamp without time zone) AND (date
<= '2019-05-13 23:59:59.999999'::timestamp without time zone))
 Planning time: 5.380 ms
 Execution time: 6633.645 ms
(12 rows)

Объяснить depesz

Ответы [ 2 ]

1 голос
/ 13 мая 2019

Прежде всего, вы используете GROUP BY без фактического выбора агрегатов.Вы также можете просто сделать SELECT DISTINCT в своем запросе.Кроме этого, вот индекс дерева B, который вы, вероятно, должны использовать:

CREATE INDEX idx ON adsets (account_id, date, platform, publisher_platform,
    adset_id);

Проблема с вашим текущим индексом состоит в том, что, хотя он и охватывает выбранные вами столбцы, он не включает столбцыкоторые появляются в предложении WHERE.Это означает, что Postgres может даже не использовать индекс, а просто сканировать всю таблицу.

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

Вот ваш обновленный запрос:

SELECT DISTINCT
    platform,
    publisher_platform,
    adset_id
FROM adsets
WHERE
    account_id IN ('1595321963838425', '1320001405',
                   'urn:li:sponsoredAccount:507697540') AND
    date >= '2019-05-06' AND date < '2019-05-14';
0 голосов
/ 13 мая 2019

Ваша проблема - множество «ложных срабатываний», которые обнаруживаются на этапе сканирования индекса растрового изображения и удаляются на этапе сканирования кучи.Поскольку дополнительного фильтра нет, я предполагаю, что лишние строки должны быть удалены, поскольку они не видны.

Посмотрите, улучшит ли VACUUM adsets производительность запроса.

...