Оптимизация этого подсчетного запроса в Postgresql - PullRequest
0 голосов
/ 06 августа 2020

Мне нужно реализовать в моем приложении базовую c боковую панель фасетного поиска. Я, к сожалению, не могу использовать альтернативы Elasticsearch / Solr / и ограничен Postgres.

У меня около 10+ столбцов ('status', 'classification', 'filing_type' ...) Мне нужно вернуть подсчитывает каждое отдельное значение после каждого выполненного поиска и отображает их соответственно. Я набрал этот бит sql, однако в долгосрочной перспективе это не уведет меня очень далеко, поскольку он значительно замедлится, когда я достигну большого количества строк.

select row_to_json(t) from (
    select 'status' as column, status as value, count(*) from api_articles_mv_temp group by status 
  union
    select 'classification' as column, classification as value, count(*) from api_articles_mv_temp group by classification 
  union 
    select 'filing_type' as column, filing_type as value, count(*) from api_articles_mv_temp group by filing_type
  union
    ...) t;

Это дает

 {"column":"classification","value":"State","count":2001}
 {"column":"classification","value":"Territory","count":23}
 {"column":"filing_type","value":"Joint","count":169}
 {"column":"classification","value":"SRO","count":771}
 {"column":"filing_type","value":"Single","count":4238}
 {"column":"status","value":"Updated","count":506}
 {"column":"classification","value":"Federal","count":1612}
 {"column":"status","value":"New","count":3901}

Исходя из плана запроса, HashAggregates замедляет его.

Subquery Scan on t  (cost=2397.58..2397.76 rows=8 width=32) (actual time=212.822..213.022 rows=8 loops=1)
  ->  HashAggregate  (cost=2397.58..2397.66 rows=8 width=186) (actual time=212.780..212.856 rows=8 loops=1)
         Group Key: ('status'::text), api_articles_mv_temp.status, (count(*))
         ->  Append  (cost=799.11..2397.52 rows=8 width=186) (actual time=75.238..212.701 rows=8 loops=1)
               ->  HashAggregate  (cost=799.11..799.13 rows=2 width=44) (actual time=75.221..75.242 rows=2 loops=1)
                     Group Key: api_articles_mv_temp.status
...

Есть ли более простой и оптимизированный способ получить этот результат?

1 Ответ

1 голос
/ 09 августа 2020

Одноразовое чтение api_articles_mv_temp может улучшить производительность. Я привел вам примеры, можете ли вы их попробовать?

  1. Если комбинации «столбец» и «значение» фиксированы, запрос будет выглядеть следующим образом:
select row_to_json(t) from (
  select "column", "value", count(*) as "count"
  from column_temp left outer join api_articles_mv_temp on
    "value"=
    case "column"
      when 'status' then status
      when 'classification' then classification
      when 'filing_type' then filing_type
    end
  group by "column", "value"
) t;

В столбце_темп есть записи ниже:

column         |value
---------------+----------
status         |New
status         |Updated
classification |State
classification |Territory
classification |SRO
filing_type    |Single
filing_type    |Joint

DB Fiddle

Если фиксирован только «столбец», запрос будет выглядеть следующим образом:
select row_to_json(t) from (
  select "column",
    case "column"
      when 'status' then status
      when 'classification' then classification
      when 'filing_type' then filing_type
    end as "value",
    sum("count") as "count"
  from column_temp a
    cross join (
      select
        status,
        classification,
        filing_type,
        count(*) as "count"
      from api_articles_mv_temp
      group by
        status,
        classification,
        filing_type) b
  group by "column", "value"
) t;

Столбец_temp содержит записи ниже:

column         
---------------
status         
classification 
filing_type    

DB Fiddle

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