摘要:通过2个实例场景讲解GaussDB(DWS)运维解决方案。

本文分享自华为云社区《GaussDB(DWS)运维 -- 基表统计信息估算不准的常见场景及处理方案》,作者:譡里个檔。

场景1:基表过滤字段存在的隐式类型时,基表行数估算偏小

这种场景绝大部分场景DWS能够处理,但是如果隐式类型转后的结果与统计信息中的字段枚举值的表达式不一样,就会导致估算的严重偏差

原始SQL如下

SELECT * FROM dmgrpdi.dwl_inv_res_rpt_ci_grp_f WHERE period_id=202212 AND source_flag=1;

对应的执行计划

                                                    QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
id | operation | E-rows | E-memory | E-width | E-costs
----+------------------------------------------------------------------+--------+----------+---------+-----------
1 | -> Row Adapter | 14160 | | 717 | 680025.43
2 | -> Vector Streaming (type: GATHER) | 14160 | | 717 | 680025.43
3 | -> Vector Partition Iterator | 14160 | 1MB | 717 | 678241.33
4 | -> Partitioned CStore Scan on dwl_inv_res_rpt_ci_grp_f | 14160 | 1MB | 717 | 678241.33
Predicate Information (identified by plan id)
-------------------------------------------------------------------------------
3 --Vector Partition Iterator
Iterations: 1
4 --Partitioned CStore Scan on dwl_inv_res_rpt_ci_grp_f
Filter: ((period_id = 202212::numeric) AND ((source_flag)::bigint = 1))
Pushdown Predicate Filter: (period_id = 202212::numeric)
Partitions Selected by Static Prune: 36

发现source_flag字段上存在隐式类型转换,查询字段source_flag的统计信息

postgres=# SELECT most_common_vals,most_common_freqs, histogram_bounds  FROM pg_stats WHERE tablename = 'dwl_inv_res_rpt_ci_grp_f' AND attname = 'source_flag';
most_common_vals | most_common_freqs | histogram_bounds
------------------+-----------------------------------+------------------
{01,02,04,03} | {.440034,.241349,.217413,.101089} | {05,06}
(1 row)

发现隐式类型转后的结果(1)与统计信息中的字段枚举值('01')的表达式不一样

处理方案:修改过滤条件,禁止类型转换,并且使用正确的常量值书写过滤条件

如上SQL语句中的source_flag=1修改为source_flag='01',修改后SQL语句如下

SELECT * FROM dmgrpdi.dwl_inv_res_rpt_ci_grp_f WHERE period_id=202212 AND source_flag='01';

查询新语句的执行计划

                                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
id | operation | E-rows | E-memory | E-width | E-costs
----+------------------------------------------------------------------+-----------+----------+---------+-----------
1 | -> Row Adapter | 108359075 | | 717 | 480542.98
2 | -> Vector Streaming (type: GATHER) | 108359075 | | 717 | 480542.98
3 | -> Vector Partition Iterator | 108359075 | 1MB | 717 | 478758.88
4 | -> Partitioned CStore Scan on dwl_inv_res_rpt_ci_grp_f | 108359075 | 1MB | 717 | 478758.88
Predicate Information (identified by plan id)
-------------------------------------------------------------------------------------------------
3 --Vector Partition Iterator
Iterations: 1
4 --Partitioned CStore Scan on dwl_inv_res_rpt_ci_grp_f
Filter: ((period_id = 202212::numeric) AND (source_flag = '01'::text))
Pushdown Predicate Filter: ((period_id = 202212::numeric) AND (source_flag = '01'::text))
Partitions Selected by Static Prune: 36

场景2:基表在多列组合主键上过滤时,基表行数估算偏大

这种场景是因为DWS对基表上多个过滤条件之间采取弱相关性处理,当多个过滤条件是主键时,可能导致结果集估算偏大。

原始SQL如下

SELECT * FROM mca.mca_period_rate_t mca_rate2
WHERE period_number = '202208' AND from_currency_code = 'RMB' AND to_currency_code = 'USD'

执行信息如下

 id |                      operation                       |       A-time | A-rows | E-rows | Peak Memory | E-memory | A-width | E-width | E-costs
----+------------------------------------------------------+--------------------+--------+--------+-------------+----------+---------+---------+----------
1 | -> Row Adapter | 444.735 | 1 | 2033 | 227KB | | | 321 | 22601.41
2 | -> Vector Streaming (type: GATHER) | 444.720 | 1 | 2033 | 873KB | | | 321 | 22601.41
3 | -> CStore Scan on mca_period_rate_t mca_rate2 | [435.167, 435.167] | 1 | 2033 | [5MB, 5MB] | 1MB | | 321 | 22427.41
Predicate Information (identified by plan id)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3 --CStore Scan on mca_period_rate_t mca_rate2
Filter: (((period_number)::text = '202208'::text) AND ((from_currency_code)::text = 'RMB'::text) AND ((to_currency_code)::text = 'USD'::text))
Rows Removed by Filter: 425812
Pushdown Predicate Filter: (((period_number)::text = '202208'::text) AND ((from_currency_code)::text = 'RMB'::text) AND ((to_currency_code)::text = 'USD'::text))

可以发现基表mca.mca_period_rate_t的行数估算严重偏大。

使用如下SQL语句查看表mca.mca_period_rate_t的定义

SELECT pg_get_tabledef('mca.mca_period_rate_t'::regclass);

查询表mca.mca_period_rate_t定义

SELECT pg_get_tabledef('mca.mca_period_rate_t');
SET search_path = mca;
CREATE TABLE mca_period_rate_t (
seq numeric NOT NULL,
period_number character varying(10) NOT NULL,
from_currency_code character varying(20) NOT NULL,
to_currency_code character varying(20) NOT NULL,
begin_rate numeric(35,18),
end_rate numeric(35,18),
avg_rate numeric(35,18),
creation_date timestamp(0) without time zone NOT NULL,
created_by numeric NOT NULL,
last_update_date timestamp(0) without time zone,
last_updated_by numeric,
rmb_begin_rate numeric(35,18),
usd_begin_rate numeric(35,18),
rmb_end_rate numeric(35,18),
usd_end_rate numeric(35,18),
rmb_avg_rate numeric(35,18),
usd_avg_rate numeric(35,18),
crt_cycle_id numeric,
crt_job_instance_id numeric,
last_upd_cycle_id numeric,
upd_job_instance_id numeric,
cdc_key_id character varying(128) DEFAULT sys_guid(),
end_rate2 numeric(35,18),
avg_rate2 numeric(35,18),
last_period_end_rate numeric(35,18)
)
WITH (orientation=column, compression=low, colversion=2.0, enable_delta=false)
DISTRIBUTE BY REPLICATION
TO GROUP group_version1;
CREATE UNIQUE INDEX mca_period_rate_u1 ON mca.mca_period_rate_t USING cbtree (period_number, from_currency_code, to_currency_code) TABLESPACE pg_default;

发现 (period_number, from_currency_code, to_currency_code) 为组合的唯一索引。

处理方案:对组合索引列收多列统计信息

注意此种方案只适用在基表比较小的情况下。因为多列统计信息需要使用百分比采样的方式计算统计信息,当表比较大时,统计信息计算耗时回很长。

针对如上查询语句执行如下语句收集(period_number, from_currency_code, to_currency_code) 多列统计信息

ANALYZE mca.mca_period_rate_t((period_number, from_currency_code, to_currency_code));

收集多列统计信息之后,基表的行数估算恢复正产

 id |                                      operation                                      |       A-time | A-rows | E-rows | Peak Memory | A-width | E-width | E-costs
----+-------------------------------------------------------------------------------------+--------------------+--------+--------+-------------+---------+---------+---------
1 | -> Row Adapter | 195.504 | 1 | 1 | 227KB | | 321 | 675.14
2 | -> Vector Streaming (type: GATHER) | 195.491 | 1 | 1 | 873KB | | 321 | 675.14
3 | -> CStore Index Scan using mca_period_rate_u1 on mca_period_rate_t mca_rate2 | [164.344, 164.344] | 1 | 1 | [5MB, 5MB] | | 321 | 501.14
Predicate Information (identified by plan id)
----------------------------------------------------------------------------------------------------------------------------------------------------------
3 --CStore Index Scan using mca_period_rate_u1 on mca_period_rate_t mca_rate2
Index Cond: (((period_number)::text = '202208'::text) AND ((from_currency_code)::text = 'RMB'::text) AND ((to_currency_code)::text = 'USD'::text))

点击关注,第一时间了解华为云新鲜技术~

2个场景实例讲解GaussDB(DWS)基表统计信息估算不准的处理方案的更多相关文章

  1. 一文详解GaussDB(DWS) 的并发管控和内存管控

    摘要:DWS的负载管理分为两层,第一层为cn的全局并发控制,第二层为资源池级别的并发控制. 本文分享自华为云社区<GaussDB(DWS) 并发管控&内存管控>,作者: fight ...

  2. 详解GaussDB(DWS) explain分布式执行计划

    摘要:本文主要介绍如何详细解读GaussDB(DWS)产生的分布式执行计划,从计划中发现性能调优点. 前言 执行计划(又称解释计划)是数据库执行SQL语句的具体步骤,例如通过索引还是全表扫描访问表中的 ...

  3. 十八般武艺玩转GaussDB(DWS)性能调优(三):好味道表定义

    摘要:表结构设计是数据库建模的一个关键环节,表定义好坏直接决定了集群的有效容量以及业务查询性能,本文从产品架构.功能实现以及业务特征的角度阐述在GaussDB(DWS)的中表定义时需要关注的一些关键因 ...

  4. 从数据仓库双集群系统模式探讨,看GaussDB(DWS)的容灾设计

    摘要:本文主要是探讨OLAP关系型数据库框架的数据仓库平台如何设计双集群系统,即增强系统高可用的保障水准,然后讨论一下GaussDB(DWS)的容灾应该如何设计. 当前社会.企业运行当中,大数据分析. ...

  5. GaussDB(DWS)应用实践丨负载管理与作业排队处理方法

    摘要:本文用来总结一些GaussDB(DWS)在实际应用过程中,可能出现的各种作业排队的情况,以及出现排队时,我们应该怎么去判断是否正常,调整一些参数,让资源分配与负载管理更符合当前的业务:或者在作业 ...

  6. 十八般武艺玩转GaussDB(DWS)性能调优:SQL改写

    摘要:本文将系统介绍在GaussDB(DWS)系统中影响性能的坏味道SQL及SQL模式,帮助大家能够从原理层面尽快识别这些坏味道SQL,在调优过程中及时发现问题,进行整改. 数据库的应用中,充斥着坏味 ...

  7. 十八般武艺玩转GaussDB(DWS)性能调优:路径干预

    摘要:路径生成是表关联方式确定的主要阶段,本文介绍了几个影响路径生成的要素:cost_param, scan方式,join方式,stream方式,并从原理上分析如何干预路径的生成. 一.cost模型选 ...

  8. GaussDB(DWS)中共享消息队列实现的三大功能

    摘要:本文将详细介绍GaussDB(DWS)中共享消息队列的实现. 本文分享自华为云社区<GaussDB(DWS)CBB组件之共享消息队列介绍>,作者:疯狂朔朔. 1)共享消息队列是什么? ...

  9. 详解GaussDB(DWS) 资源监控

    摘要:本文主要着重介绍资源池资源监控以及用户资源监控. 本文分享自华为云社区<GaussDB(DWS)资源监控之用户.队列资源监控>,作者: 一只菜菜鸟. GaussDB(DWS)资源监控 ...

  10. 一文详解数仓GaussDB(DWS) 函数出参带出方式

    摘要:本文主要讲解DWS函数出参带出方式. 本文分享自华为云社区<GaussDB(DWS)功能 -- 函数出参 #[玩转PB级数仓GaussDB(DWS)]>,作者:譡里个檔 . DWS的 ...

随机推荐

  1. 一次spark任务提交参数的优化

    起因 新接触一个spark集群,明明集群资源(core,内存)还有剩余,但是提交的任务却申请不到资源. 分析 环境 spark 2.2.0 基于yarn集群 参数 spark任务提交参数中最重要的几个 ...

  2. Vue 相关整理

    一 谈谈对 keep-alive 的了解? keep-alive 是Vue内置的一个组件,可以使被包含的组件保留状态,避免重新渲染,其有以下特性: * 一般结合路由和动态组件一起使用,用于缓存组件: ...

  3. [ACM]TL-Prim

    #include<iostream> #include<cstdio> using namespace std; int main(){ int inf = 99999999; ...

  4. 补五月五号java基础知识点

    1.容器类:容器类是java以类库的形式供有用户开发程序时可直接使用的各种数据结构.2.java容器框架中有两个名称分别为Collection和Set的接口,为防止名称的冲突,本书将Collectio ...

  5. 进程,Process模块,join方法,ipc机制,守护进程

    多道技术: """ 在学习并发编程的过程中 不做刻意提醒的情况下 默认一台计算机就一个CPU(只有一个干活的人) """ 单道技术 所有的程 ...

  6. 多线程socketserver

    模块:socketserver tcp协议: 服务端: import socketserver class MyRequestHandle(socketserver.BaseRequestHandle ...

  7. DG:有多个备库如何切换

    问题描述:有一数据库准备进行主备switchover切换,但是有两个备库,其中最早一个备库状态已经出现GAP,第二个备库状态正常 SQL> show parameter log_archive_ ...

  8. GIL和池的概念

    1.GIL概念 1. 什么是GIL(为Cpython解释器) GIL本身就是一把互斥锁. 原理都一样. 都是让并发的线程同一时间只能执行一个 所以有了GIL的存在. 同一进程下的多个线程同一时刻只能有 ...

  9. STIL 格式pattern介绍

    相信很多工程师,特别是刚入行或准备入行的兄弟们或多或少听过测试相关的东西.如果你想做DFT工程师的,测试工程师的,而对于设计/验证工程师们如果能了解下STIL文件的原理,在和DFT/测试工程师聊技术聊 ...

  10. 【介绍】C++五种迭代器

    目录 1. 输入迭代器(Input Iterator): 2. 输出迭代器(Output Iterator): 3. 前向迭代器(Forward Iterator): 4. 双向迭代器(Bidirec ...