提高选择查询的性能

问题描述 投票:0回答:1

我有这个物化视图,它聚合来自多个表的数据,这些表存储有关我的应用程序中的统计数据的信息。目前,此视图包含大约800.000条记录。问题是这个查询运行得很慢(大约1.5秒)并且不能满足客户的需求。有没有办法改善其表现?我正在使用PostgreSQL 9.6。

我试过创建索引。但它没有帮助。

CREATE INDEX t1 ON statistic_basic_view (active, visible, removed, draft, id, name, object_type, is_paid, company_name);

CREATE INDEX t2 ON statistic_basic_view (company_name, is_paid, object_type, name, id, draft, removed, visible, active);

CREATE INDEX t3 ON statistic_basic_view (company_name, is_paid, object_type, name, id);

CREATE INDEX t4 ON statistic_basic_view (draft, removed, visible, active);

CREATE INDEX t5 ON statistic_basic_view (active, visible, removed, draft);

CREATE INDEX t6 ON statistic_basic_view (id, name, object_type, is_paid, company_name);

CREATE INDEX t8 ON statistic_basic_view (active, visible, removed, draft, id, name, object_type, is_paid, company_name);

CREATE INDEX t9 ON statistic_basic_view ((active AND visible AND (NOT removed) AND (NOT draft)));

CREATE INDEX t10 ON statistic_basic_view (((NOT draft) AND (NOT removed) AND active = true AND visible = true));

查询:

SELECT id,
       name,
       object_type,
       is_paid,
       company_name,
       SUM(CASE
             WHEN type = 'COMPARE'
               AND service_type IN ('GG_WEB') THEN 1
             ELSE 0
         END) AS compare_count,
       SUM(CASE
             WHEN type = 'EXPORT'
               AND service_type IN ('GG_WEB') THEN 1
             ELSE 0
         END) AS export_count,
       SUM(CASE
             WHEN type = 'VIEW'
               AND service_type IN ('GG_WEB') THEN 1
             ELSE 0
         END) AS view_count,
       SUM(CASE
             WHEN type = 'REMEMBER'
               AND service_type IN ('GG_WEB') THEN 1
             ELSE 0
         END) AS remember_count,
       SUM(CASE
             WHEN type = 'SEARCH'
               AND service_type IN ('GG_WEB') THEN 1
             ELSE 0
         END) AS search_count,
       SUM(CASE
             WHEN type = 'MAIL'
               AND service_type IN ('GG_WEB') THEN 1
             ELSE 0
         END) AS mail_count
FROM statistic_basic_view
WHERE active = TRUE
  AND visible = TRUE
  AND removed = FALSE
  AND draft = FALSE
GROUP BY id,
         name,
         object_type,
         is_paid,
         company_name
ORDER BY view_count DESC,
         id ASC
limit 15;

解释分析:

Limit  (cost=74204.47..74204.50 rows=15 width=130) (actual time=1420.542..1420.545 rows=15 loops=1)
  ->  Sort  (cost=74204.47..74600.55 rows=158432 width=130) (actual time=1420.540..1420.542 rows=15 loops=1)
        Sort Key: (sum(CASE WHEN ((type = 'VIEW'::text) AND ((service_type)::text = 'GG_WEB'::text)) THEN 1 ELSE 0 END)) DESC, id
        Sort Method: top-N heapsort  Memory: 28kB
        ->  HashAggregate  (cost=68733.10..70317.43 rows=158432 width=130) (actual time=1420.539..1420.542 rows=8988 loops=1)
              Group Key: id, name, object_type, is_paid, company_name
              ->  Seq Scan on statistic_basic_view  (cost=0.00..24950.65 rows=761434 width=94) (actual time=0.023..249.851 rows=762118 loops=1)
                    Filter: (active AND visible AND (NOT removed) AND (NOT draft))
                    Rows Removed by Filter: 30047
Planning time: 0.665 ms
Execution time: 1420.545 ms
postgresql indexing query-performance materialized-views
1个回答
1
投票

没有索引可以帮助您解决此问题。

没有WHERE条件是选择性的,你不能使用索引加速那么多组的GROUP BY,并且你不能使用索引进行排序(因为在此之前有不同标准的分组)。

你应该做的是在物化视图之上(或直接在基表之上)创建另一个materialized view,它具有预先计算的结果并定期刷新。这为您提供了稍微过时的数据,但速度很快。

© www.soinside.com 2019 - 2024. All rights reserved.