Производительность для запроса представления PostgreSQL - PullRequest
1 голос
/ 06 июня 2019

У меня есть нормальное представление, которое было перенесено с SQL Server 2000 на PostgreSQL 11, который прекрасно работает в SQL Server, но в PostgreSQL это занимает более чем вдвое больше времени, что слишком долго.

Я сделалвакуум таблиц и созданных индексов, но, может быть, я что-то упустил.Мне нужна помощь в тонкой настройке запроса.

SELECT h.bg AS bg,
    count(*) AS cnt,
    sum(h.retail_score) AS retail_score
   FROM ( SELECT x.bg,
                CASE x.void_category
                    WHEN 'DEPARTMENT STORE'::citext THEN 0.6
                    WHEN 'THEATERS/CINEMA'::citext THEN 0.5
                    WHEN 'SUPERCENTER'::citext THEN 0.35
                    WHEN 'CLOTHING AND APPAREL'::citext THEN 0.3
                    WHEN 'FOOTWEAR/SHOES'::citext THEN 0.2
                    WHEN 'HOME SPECIALTY'::citext THEN 0.2
                    WHEN 'HOME IMPROVEMENT'::citext THEN 0.15
                    WHEN 'OFFICE SUPPLY/SERVICES'::citext THEN 0.15
                    WHEN 'PET SUPPLIES/SERVICES'::citext THEN 0.15
                    WHEN 'BOOKSTORE'::citext THEN 0.15
                    WHEN 'RESTAURANT - FINE DINING'::citext THEN 0.15
                    WHEN 'GROCERY STORE'::citext THEN 0.15
                    WHEN 'SPORTING GOODS'::citext THEN 0.12
                    WHEN 'SPECIALTY RETAIL'::citext THEN 0.1
                    WHEN 'HOBBIES, TOYS AND CRAFTS'::citext THEN 0.09
                    WHEN 'OTHER FOOD/BEVERAGE'::citext THEN 0.08
                    WHEN 'RESTAURANT - CASUAL'::citext THEN 0.07
                    WHEN 'CONSUMER ELECTRONICS'::citext THEN 0.07
                    WHEN 'FITNESS AND GYMS'::citext THEN 0.05
                    WHEN 'GENERAL MERCHANDISE'::citext THEN 0.05
                    WHEN 'PHARMACY/DRUG STORE'::citext THEN 0.04
                    WHEN 'PAYDAY LOAN'::citext THEN 0.02
                    WHEN 'HAIR, SKIN AND NAILS'::citext THEN 0.01
                    WHEN 'RESTAURANT - OTHER'::citext THEN 0.01
                    WHEN 'RESTAURANT - QUICK SERVICE'::citext THEN 0.01
                    WHEN 'COFFEE SHOP'::citext THEN 0.01
                    ELSE 0::numeric
                END AS retail_score
           FROM sometable x
          WHERE x.void_include = 'Y'::citext) h
  GROUP BY h.bg;

План выполнения:

"Finalize GroupAggregate  (cost=100341.22..155233.07 rows=78181 width=53) (actual time=19217.400..73474.255 rows=138934 loops=1)"
"  Group Key: sometable.bg"
"  ->  Gather Merge  (cost=100341.22..152692.19 rows=156362 width=53) (actual time=19216.226..72095.206 rows=278778 loops=1)"
"        Workers Planned: 2"
"        Workers Launched: 2"
"        ->  Partial GroupAggregate  (cost=99341.20..133644.11 rows=78181 width=53) (actual time=18448.896..45748.827 rows=92926 loops=3)"
"              Group Key: sometable.bg"
"              ->  Sort  (cost=99341.20..100452.06 rows=444342 width=31) (actual time=18448.677..21747.908 rows=355865 loops=3)"
"                    Sort Key: sometable.bg"
"                    Sort Method: external merge  Disk: 19064kB"
"                    Worker 0:  Sort Method: external merge  Disk: 10912kB"
"                    Worker 1:  Sort Method: external merge  Disk: 13016kB"
"                    ->  Parallel Index Scan using idx_ix_xd_here_9 on sometable  (cost=0.43..47026.01 rows=444342 width=31) (actual time=0.197..746.601 rows=355865 loops=3)"
"                          Index Cond: (void_include = 'Y'::citext)"
"Planning Time: 0.470 ms"
"Execution Time: 73499.182 ms"

Я хотел бы увидеть, что я сделал неправильно или забыл, и научиться улучшать запрос SQL.

Основываясь на предложении Лоренца, я попробовал следующее: но все еще не хорошо ...: (

SET work_mem = '256MB';
"Finalize HashAggregate  (cost=98417.89..99395.15 rows=78181 width=53) (actual time=40369.734..40511.007 rows=138934 loops=1)"
"  Group Key: sometable.bg"
"  ->  Gather  (cost=80240.80..96854.27 rows=156362 width=53) (actual time=38567.902..38978.588 rows=276820 loops=1)"
"        Workers Planned: 2"
"        Workers Launched: 2"
"        ->  Partial HashAggregate  (cost=79240.80..80218.07 rows=78181 width=53) (actual time=38350.897..38449.107 rows=92273 loops=3)"
"              Group Key: sometable.bg"
"              ->  Parallel Index Scan using idx_ix_xd_here_9 on sometable  (cost=0.43..47026.01 rows=444342 width=31) (actual time=0.173..677.385 rows=355865 loops=3)"
"                    Index Cond: (void_include = 'Y'::citext)"
"Planning Time: 0.333 ms"
"Execution Time: 40546.180 ms"

SET work_mem = '1024MB';

"Finalize HashAggregate  (cost=98417.89..99395.15 rows=78181 width=53) (actual time=35633.509..35717.539 rows=138934 loops=1)"
"  Group Key: sometable.bg"
"  ->  Gather  (cost=80240.80..96854.27 rows=156362 width=53) (actual time=34612.949..34783.491 rows=277896 loops=1)"
"        Workers Planned: 2"
"        Workers Launched: 2"
"        ->  Partial HashAggregate  (cost=79240.80..80218.07 rows=78181 width=53) (actual time=34369.871..34446.030 rows=92632 loops=3)"
"              Group Key: sometable.bg"
"              ->  Parallel Index Scan using idx_ix_xd_here_9 on sometable  (cost=0.43..47026.01 rows=444342 width=31) (actual time=0.176..585.221 rows=355865 loops=3)"
"                    Index Cond: (void_include = 'Y'::citext)"
"Planning Time: 0.337 ms"
"Execution Time: 35735.606 ms"

1 Ответ

0 голосов
/ 06 июня 2019

Вы должны увеличить work_mem, чтобы ускорить этот запрос.

Тогда медленная сортировка может быть выполнена в памяти, и вы, вероятно, даже можете получить HashAggregate вместо GroupAggregate, что полностью исключает сортировку.

...