【问题标题】:Query optimization on timestamp and group by in PostgreSQLPostgreSQL 中时间戳和分组依据的查询优化
【发布时间】:2019-11-17 00:08:29
【问题描述】:

我想用以下结构查询我的表:

               Table "public.company_geo_table"
       Column       |  Type  | Collation | Nullable | Default 
--------------------+--------+-----------+----------+---------
 geoname_id         | bigint |           |          | 
 date               | text   |           |          | 
 cik                | text   |           |          | 
 count              | bigint |           |          | 
 country_iso_code   | text   |           |          | 
 subdivision_1_name | text   |           |          | 
 city_name          | text   |           |          | 
Indexes:
    "cik_country_index" btree (cik, country_iso_code)
    "cik_geoname_index" btree (cik, geoname_id)
    "cik_index" btree (cik)
    "date_index" brin (date)

我尝试使用以下 sql 查询,它需要在一个时间段内查询特定的 cik 编号,并按带有 geoname_id(不同区域)的 cik 分组。

select cik, geoname_id, sum(count) as total
from company_geo_table
where cik = '1111111'
and date between '2016-01-01' and '2016-01-10'
group by cik, geoname_id

解释结果显示他们只使用了cik索引和日期索引,没有使用cik_geoname索引。为什么?有什么办法可以优化我的解决方案吗?有什么新指标吗?提前谢谢你。

HashAggregate  (cost=117182.79..117521.42 rows=27091 width=47) (actual time=560132.903..560134.229 rows=3552 loops=1)
   Group Key: cik, geoname_id
   ->  Bitmap Heap Scan on company_geo_table  (cost=16467.77..116979.48 rows=27108 width=23) (actual time=6486.232..560114.828 rows=8175 loops=1)
         Recheck Cond: ((date >= '2016-01-01'::text) AND (date <= '2016-01-10'::text) AND (cik = '1288776'::text))
         Rows Removed by Index Recheck: 16621155
         Heap Blocks: lossy=193098
         ->  BitmapAnd  (cost=16467.77..16467.77 rows=27428 width=0) (actual time=6469.640..6469.641 rows=0 loops=1)
               ->  Bitmap Index Scan on date_index  (cost=0.00..244.81 rows=7155101 width=0) (actual time=53.034..53.035 rows=8261120 loops=1)
                     Index Cond: ((date >= '2016-01-01'::text) AND (date <= '2016-01-10'::text))
               ->  Bitmap Index Scan on cik_index  (cost=0.00..16209.15 rows=739278 width=0) (actual time=6370.930..6370.930 rows=676231 loops=1)
                     Index Cond: (cik = '1111111'::text)
 Planning time: 12.909 ms
 Execution time: 560135.432 ms

【问题讨论】:

  • 索引用于更快地搜索数据,因此应在连接或输入值中使用键。这里 cik_geoname_index 是为 (cik, geoname_id) 创建的,所以当两个列在 where 条件/joins/with 输入值中使用时都会使用它。但在您的情况下,geoname_id 字段不是连接/输入值的一部分。

标签: postgresql indexing timestamp query-optimization


【解决方案1】:

没有很好的估计(可能值'1111111'被使用得太频繁了(我不确定影响,但看起来cik列有错误的数据类型(文本),可能是什么原因(或部分原因)估计不好。

Bitmap Heap Scan on company_geo_table  (cost=16467.77..116979.48 rows=27108 width=23) (actual time=6486.232..560114.828 rows=8175 loops=1)

看起来复合索引 (date, cik) 可以提供帮助

【讨论】:

  • 感谢重播。 '1111111' 只是一个例子,不是一个真实的值。 'cik' 是每个公司的唯一标识符,所以我认为 text 是合理的。
【解决方案2】:

您的问题似乎在这里:

Rows Removed by Index Recheck: 16621155
Heap Blocks: lossy=193098

您的work_mem 设置太低,因此 PostgreSQL 无法容纳每个表行包含一位的位图,因此它会降级为每 8K 块一位。这意味着在位图堆扫描期间必须删除许多误报命中。

尝试使用更高的work_mem,看看是否会提高查询性能。

理想的索引应该是

CREATE INDEX ON company_geo_table (cik, date);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 2012-12-09
    • 2015-04-02
    • 2021-11-05
    • 2014-06-13
    • 2022-01-12
    相关资源
    最近更新 更多