-
背景及现象描述(Background and Symptom)*1. 环境信息:GaussDB A 8.0.0版本12节点集群2. 问题现象:客户反映业务执行慢,原本几分钟的业务一个小时都跑不完,造成大量业务累计。 3. 分析过程1. 初步分析为客户连接数过高导致IO高,限制连接数后IO稍有回落,后续IO又升高至95%以上且限制连接数后严重影响用户使用2. 连到数据库,查用线程的id,查pgxc_thread_wait_status,可以找到对应语句的query_id可以看到该sql处理flush data状态3. 检查下盘文件,发现每个数据目录下均有不等的下盘文件,且个别sql的下盘文件数达到3000+下盘文件中间部分的id为query_id,根据query_id找到对应的sql与业务侧同事确认该sql不合理,需要整改4. 确认work_mem设置大小当前集群work_mem设置为512MB,设置的过小导致下盘情况容易产生,目前调整为3GB原因分析(Cause Analysis)*当work_mem设置较小场景时,会产生大量的下盘,时时在数据盘上读写文件,导致数据盘读写IO繁忙,因此影响其他业务运行。解决办法(Solution)*(1) 调整work_mem,使其满足大部分业务的使用场景(2) 整改不合理业务,使客户系统运行更顺畅。
-
华为商城(Vmall商城)隶属于华为技术有限公司,是华为公司旗下的自营电子商务平台,以最终用户为主要对象,提供华为手机、无线上网设备、平板电脑、配件等系列终端产品和服务;是以营造用户的移动信息生活为服务宗旨的互联网商务平台。2012年3月,华为商城内部测试版正式对外试运营,并于3月18日正式上线营业。 在华为产品的众多销售渠道中,华为商城具有以下优势:正品保证:华为商城为华为终端自有官方销售服务网站。提供全系列华为产品,保证正品、服务可靠!一站式的网站体验:华为商城一站式提供产品和服务。服务无忧:从商品、验货、库存、配货售后服务等环节全方位保证商品品质。社区互动优势:发挥已有社区的优势,增加官方与用户、用户与用户的互动。 随着华为消费者产品的销售的持续增长,作为消费者产品的最重要渠道之一,Vmall是如何支撑保障华为终端业务的快速发展呢?今天我们就为大家来解密Vmall商城成功背后的秘密。 一个成熟的电商平台,一般至少包含以下几个功能:门户Portal、交易系统、端侧APP、用户画像、推荐系统、搜索系统、报表等。究竟Vmall商城通过是什么神秘的技术力量,保障这些系统有机高效的运行,来成就Vmall商业上的成功呢? 下面我们就来为大家揭秘Vmall的大厦是如何建成的?我们仅以报表、营销、画像、推荐等几个核心系统来介绍整个系统是如何有机运行。话不多说,请看图: 整个系统的数据来源包含2部分,一部分来自于交易系统,包括产品管理系统、订单管理系统、客户管理系统、风险管理系统等等。另一部分数据来自于端测的流数据,包括用户点击率、商品搜索等行为数据。从软件架构上来看,这些数据都被流入、汇聚到一个DWS集群中,并且,整个框架的ODS层、DWI/DWD、DWS、DM层,都是构筑于同一套DWS集群中。因此,DWS才是这一系列魔法的关键。 报表系统的数据流如下: 业务系统将数据映像到TiDB中。通过CDM和ROMA服务将数据同步至DWS中。经过SDI、DWD/DWI层加工后,在DWS层进行进一步加工,生成面向各个主体的DM层数据。OAR数据系统通过调用相应DM层数据,进行报表和大屏数据呈现。 说到营销,就不得不提到画像系统。画像是推荐和营销、搜索的基石。画像系统的数据主要来自于对端侧行为数据的分析归类,其业务流程如下:端侧行为数据通过DAP模块汇聚至kafka组件。通过CSS组件(Flink)将数据实时汇聚只DWS中。在DWS中通过标签算法,对用户行为进行标签、分析和归类。将相关标签同步至ES中进行画像查询。 营销系统数据流程如下:基于画像相关的流程基础上,将ES中的画像数据同步至DMP平台。基于DMP平台进行营销获得的策划、编排、跟踪等。 推荐系统和搜索系统强相关的。因为推荐系统需要调用画像、商品等信息。Vmall商城的搜索系统基于华为云ES服务之上,使用了增强的泊松引擎,通过RPC网关,对外提供搜索RPC API接口调用,为商城Web端和移动端APP提供商品搜索和推荐服务。 在整个华为商城的架构中,DWS服务起到了极其重要核心的作用。既有效地承载了传统数仓的批处理和高并发查询任务,又完美实现了高并发实时流数据的接入和实时分析,经受住了618等重大业务极限流量高峰的考验,成为华为商城数据处理基座的中流砥柱。 那么,华为云DWS服务究竟是如何做到这些,这里面又包含了哪些不为人所熟知的独门秘技呢,请听下回分解!
-
【功能模块】创建外表报分区边界过小【操作步骤&问题现象】1、创建表的多个字段 range 分区 2、建表失败报错如下【截图信息】建表语句见附件【日志信息】(可选,上传日志内容或者附件)其他表这么建是可以的。
-
数据倾斜问题是分布式架构的重要难题,它破坏了MPP架构中各个节点对等的要求,导致单节点(倾斜节点)所存储或者计算的数据量远大于其他节点,所以会造成以下危害:存储上的倾斜会严重限制系统容量,在系统容量不饱和的情况下,由于单节点倾斜的限制,使得整个系统容量无法继续增长。计算上的倾斜会严重影响系统性能,由于倾斜节点所需要运算的数据量远大于其它节点,导致倾斜节点降低系统整体性能。数据倾斜还严重影响了MPP架构的扩展性。由于在存储或者计算时,往往会将相同值的数据放到同一节点,因此当倾斜数据(大量数据的值相同)出现之后,即使我们增加节点,系统瓶颈仍然受限于倾斜节点的容量或者性能。GaussDB(DWS)数据库针对数据倾斜问题给出了完整的解决方案,下面简单介绍一下GaussDB(DWS)倾斜优化的机制和效果1. 预置条件CREATE TABLE t1(a int, b int) DISTRIBUTE BY HASH(a); CREATE TABLE t2(a int, b int) DISTRIBUTE BY HASH(a); INSERT INTO t1 VALUES (generate_series(1, 1000), generate_series(1, 1000)); INSERT INTO t1 SELECT a+1000*2, b+1000*2 FROM t1; INSERT INTO t1 SELECT a+1000*2*2, b+1000*2*2 FROM t1; INSERT INTO t1 SELECT a+1000*2*2*2, b+1000*2*2*2 FROM t1; INSERT INTO t1 SELECT a+1000*2*2*2*2, b+1000*2*2*2*2 FROM t1; INSERT INTO t1 SELECT a+1000*2*2*2*2*2, b+1000*2*2*2*2*2 FROM t1; INSERT INTO t1 SELECT a+1000*2*2*2*2*2*2, b+1000*2*2*2*2*2*2 FROM t1; INSERT INTO t1 SELECT a+1000*2*2*2*2*2*2*2, b+1000*2*2*2*2*2*2*2 FROM t1; INSERT INTO t2 SELECT a, 1 FROM t1; ANALYZE t1; ANALYZE t2;2. 执行概述以如下SQL为例,分析普通执行机制和倾斜优化执行机制的差异SELECT count(1) FROM t1 INNER JOIN t2 ON t1.b = t2.b;2.1 非倾斜优化执行机制GaussDB(DWS)默认采取倾斜优化执行机制。在在生成执行计划阶段,优化器根据统计信息识别杂在join列上是否存在倾斜情况,如果识别存在倾斜,自动生成优化优化计划。同时GaussDB(DWS)提供了配置参数skew_option,设置此参数为off之后,优化器会skip倾斜优化计划。postgres=# SET skew_option TO off; SET postgres=# explain analyze SELECT count(1) FROM t1 INNER JOIN t2 ON t1.b = t2.b; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------- id | operation | A-time | A-rows | E-rows | Peak Memory | E-memory | A-width | E-width | E-costs ----+--------------------------------------------+--------------------+--------+--------+--------------+----------+---------+---------+---------- 1 | -> Aggregate | 371.797 | 1 | 1 | 10KB | | | 8 | 14928.22 2 | -> Streaming (type: GATHER) | 371.693 | 4 | 4 | 79KB | | | 8 | 14928.22 3 | -> Aggregate | [236.825, 350.166] | 4 | 4 | [10KB, 10KB] | 1MB | | 8 | 14918.22 4 | -> Hash Join (5,7) | [236.817, 298.880] | 128000 | 128000 | [4KB, 5KB] | 1MB | | 0 | 14838.21 5 | -> Streaming(type: BROADCAST) | [82.726, 144.617] | 512000 | 512000 | [53KB, 53KB] | 2MB | | 4 | 13168.21 6 | -> Seq Scan on t2 | [15.528, 25.093] | 128000 | 128000 | [12KB, 12KB] | 1MB | | 4 | 469.00 7 | -> Hash | [35.826, 69.033] | 128000 | 128000 | [1MB, 1MB] | 16MB | [20,20] | 4 | 470.00 8 | -> Seq Scan on t1 | [17.163, 35.748] | 128000 | 128000 | [12KB, 12KB] | 1MB | | 4 | 470.00 Predicate Information (identified by plan id) --------------------------------------------- 4 --Hash Join (5,7) Hash Cond: (t2.b = t1.b) Memory Information (identified by plan id) -------------------------------------------------------------------- Coordinator Query Peak Memory: Query Peak Memory: 1MB Datanode: Max Query Peak Memory: 4MB Min Query Peak Memory: 4MB 7 --Hash Max Buckets: 32768 Max Batches: 1 Max Memory Usage: 1130kB Min Buckets: 32768 Min Batches: 1 Min Memory Usage: 1120kB User Define Profiling ---------------------------------------------------------------- Segment Id: 3 Track name: Datanode build connection (actual time=[0.759, 15.526], calls=[1, 1]) Segment Id: 3 Track name: Datanode wait connection (actual time=[0.001, 0.638], calls=[1, 1]) Plan Node id: 2 Track name: coordinator get datanode connection (actual time=[0.032, 0.032], calls=[1, 1]) ====== Query Summary ===== ------------------------------------------------------------------------------- Datanode executor start time [dn_6003_6004, dn_6001_6002]: [2.036 ms,16.202 ms] Datanode executor end time [dn_6007_6008, dn_6001_6002]: [0.606 ms,1.310 ms] System available mem: 3112960KB Query Max mem: 3112960KB Query estimated mem: 6690KB Coordinator executor start time: 0.529 ms Coordinator executor run time: 372.044 ms Coordinator executor end time: 0.436 ms Planner runtime: 1.156 ms Query Id: 72339069014639413 Total runtime: 373.079 ms (49 rows)正常机制下,t1和t2表都会按照b列做数据重分,重分布之后在各个DN上进行JOIN操作。但是此处的表t2的数据比较特殊,表t2的字段b上值为1比例高达100%,这样的话重分布之后值1所在DN上的计算量会比其它DN大,我们一般称之为计算倾斜。计算倾斜一般会导致两个问题1)重负载DN上资源开销比较大,导致集群负载不均衡2)重负载DN上计算耗时较长,短板效应导致SQL执行时间变长针对这种场景GaussDB(DWS)进行了特殊的倾斜执行优化2.2 倾斜优化执行机制postgres=# RESET skew_option; RESET postgres=# explain analyze SELECT count(1) FROM t1 INNER JOIN t2 ON t1.b = t2.b; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- id | operation | A-time | A-rows | E-rows | Peak Memory | E-memory | A-width | E-width | E-costs ----+----------------------------------------------------------------------+--------------------+--------+--------+--------------+----------+---------+---------+--------- 1 | -> Aggregate | 182.837 | 1 | 1 | 10KB | | | 8 | 7309.01 2 | -> Streaming (type: GATHER) | 182.748 | 4 | 4 | 79KB | | | 8 | 7309.01 3 | -> Aggregate | [158.711, 169.947] | 4 | 4 | [10KB, 10KB] | 1MB | | 8 | 7299.01 4 | -> Hash Join (5,7) | [147.187, 156.273] | 128000 | 128000 | [5KB, 5KB] | 1MB | | 0 | 7219.00 5 | -> Streaming(type: PART REDISTRIBUTE PART ROUNDROBIN) | [16.308, 23.164] | 128000 | 128000 | [53KB, 53KB] | 2MB | | 4 | 3189.00 6 | -> Seq Scan on t2 | [14.062, 17.578] | 128000 | 128000 | [12KB, 12KB] | 1MB | | 4 | 469.00 7 | -> Hash | [87.374, 92.295] | 128003 | 128000 | [1MB, 1MB] | 16MB | [20,20] | 4 | 3190.00 8 | -> Streaming(type: PART REDISTRIBUTE PART BROADCAST) | [51.194, 56.189] | 128003 | 128000 | [61KB, 61KB] | 2MB | | 4 | 3190.00 9 | -> Seq Scan on t1 | [13.989, 15.170] | 128000 | 128000 | [12KB, 12KB] | 1MB | | 4 | 470.00 Predicate Information (identified by plan id) -------------------------------------------------------- 4 --Hash Join (5,7) Hash Cond: (t2.b = t1.b) Skew Join Optimized by Statistic 5 --Streaming(type: PART REDISTRIBUTE PART ROUNDROBIN) Skew Filter: (b = 1) 8 --Streaming(type: PART REDISTRIBUTE PART BROADCAST) Skew Filter: (b = 1) Memory Information (identified by plan id) -------------------------------------------------------------------- Coordinator Query Peak Memory: Query Peak Memory: 1MB Datanode: Max Query Peak Memory: 6MB Min Query Peak Memory: 6MB 7 --Hash Max Buckets: 32768 Max Batches: 1 Max Memory Usage: 1131kB Min Buckets: 32768 Min Batches: 1 Min Memory Usage: 1120kB User Define Profiling ---------------------------------------------------------------- Segment Id: 3 Track name: Datanode build connection (actual time=[2.924, 7.101], calls=[1, 1]) Segment Id: 3 Track name: Datanode wait connection (actual time=[0.000, 1.478], calls=[1, 1]) Plan Node id: 2 Track name: coordinator get datanode connection (actual time=[0.025, 0.025], calls=[1, 1]) ====== Query Summary ===== ------------------------------------------------------------------------------ Datanode executor start time [dn_6005_6006, dn_6003_6004]: [3.544 ms,8.513 ms] Datanode executor end time [dn_6005_6006, dn_6001_6002]: [0.450 ms,0.576 ms] System available mem: 3112960KB Query Max mem: 3112960KB Query estimated mem: 8802KB Coordinator executor start time: 0.665 ms Coordinator executor run time: 183.161 ms Coordinator executor end time: 0.607 ms Planner runtime: 1.517 ms Query Id: 72339069014639134 Total runtime: 184.519 ms针对计算倾斜场景下,在数据重分布的时候对倾斜值进行特殊优化。此查询中JOIN的外表t2的字段b在值1上有倾斜内外表除了1之外的值按照正常机制进行分布和计算 对于外表(t2)上重分布字段b为1的值,进行roundrobin分布(均匀打散到各个DN上)对于内表(t1)上重分布字段b为1的值,进行broadcast分布(每个DN都保留一份)注:除非t1表是复制分布,否则PART ROUNDROBIN和PART BROADCAST总是配对出现通过这种分布机制,可以把外表重分布字段b为1的值的计算压力均摊到各个DN上,从而避免计算倾斜问题。从上述也可以看出比较明显的优化效果
-
活动分享【直播主题】GaussDB(for openGauss)数据存储与访问【直播时间】2021年4月9日 16:00~17:00【直播简介】1. 华为云数据库 GaussDB(for openGauss)数据分布方式2. 华为云数据库 GaussDB(for openGauss)读写流程3. 华为云数据库 GaussDB(for openGauss)功能演示【报名入口】点我马上报名,准时收看直播进入直播报名页,点击立即报名,报名成功即可获得100码豆。详细看报名页的直播福利,本贴只是分享贴。分享报名链接:https://bbs.huaweicloud.com/signup/0d9e2beb3ea841a882a45924ef783012?invitation=10f993b6c8644487bb91465120a7a587
-
【摘要】 GaussDB (DWS)产品数据脱敏功能,是数据库产品内化和夯实数据安全能力的重要技术突破。提供指定用户范围内列级敏感数据的脱敏功能,具有灵活、高效、透明、友好等优点,极大地增强产品的数据安全能力,实现敏感数据的可靠保护。更佳阅读体验,请移步【原创】GaussDB(DWS)安全:隐私保护现真招儿——数据脱敏引言 大数据时代的到来,颠覆了传统业态的运作模式,激发出新的生产潜能。数据成为重要的生产要素,是信息的载体,数据间的流动也潜藏着更高阶维度的价值信息。对于数据控制者和数据处理者而言,如何最大化数据流动的价值,是数据挖掘的初衷和意义。然而,一系列信息泄露事件的曝光,使得数据安全越来越受到广泛的关注。各国各地区逐步建立健全和完善数据安全与隐私保护相关法律法规,提供用户隐私保护的法律保障。如何加强技术层面的数据安全和隐私保护,对数据仓库产品本身提出更多的功能要求,也是数据安全建设最行之有效的办法。 GaussDB (DWS)产品8.1.1版本发布数据脱敏特性,提供指定用户范围内列级敏感数据的脱敏功能,具有灵活、高效、透明、友好等优点,极大地增强产品的数据安全能力。什么是数据脱敏? 数据脱敏(Data Masking),顾名思义,是屏蔽敏感数据,对某些敏感信息(比如,身份证号、手机号、卡号、客户姓名、客户地址、邮箱地址、薪资等等 )通过脱敏规则进行数据的变形,实现隐私数据的可靠保护。业界常见的脱敏规则有,替换、重排、加密、截断、掩码,用户也可以根据期望的脱敏算法自定义脱敏规则。 通常,良好的数据脱敏实施,需要遵循如下两个原则,第一,尽可能地为脱敏后的应用,保留脱敏前的有意义信息;第二,最大程度地防止黑客进行破解。 数据脱敏分为静态数据脱敏和动态数据脱敏。静态数据脱敏,是数据的“搬移并仿真替换”,是将数据抽取进行脱敏处理后,下发给下游环节,随意取用和读写的,脱敏后数据与生产环境相隔离,满足业务需求的同时保障生产数据库的安全。动态数据脱敏,在访问敏感数据的同时实时进行脱敏处理,可以为不同角色、不同权限、不同数据类型执行不同的脱敏方案,从而确保返回的数据可用而安全。 GaussDB (DWS)的数据脱敏功能,摒弃业务应用层脱敏依赖性高、代价大等痛点,将数据脱敏内化为数据库产品自身的安全能力,提供了一套完整、安全、灵活、透明、友好的数据脱敏解决方案,属于动态数据脱敏。用户识别敏感字段后,基于目标字段,绑定内置脱敏函数,即可创建脱敏策略。脱敏策略(Redaction Policy)与表对象是一一对应的。一个脱敏策略包含表对象、生效条件、脱敏列-脱敏函数对三个关键要素,是该表对象上所有脱敏列的集合,不同字段可以根据数据特征采用不同的脱敏函数。当且仅当生效条件为真时,查询语句才会触发敏感数据的脱敏,而脱敏过程是内置在SQL引擎内部实现的,对生成环境用户是透明不可见的。怎么用数据脱敏? 动态数据脱敏,是在查询语句执行过程中,根据生效条件是否满足,实现实时的脱敏处理。生效条件,通常是针对当前用户角色的判断。敏感数据的可见范围,即是针对不同用户预设的。系统管理员,具有最高权限,任何时刻对任何表的任何字段都可见。确定受限制用户角色,是创建脱敏策略的第一步。 敏感信息依赖于实际业务场景和安全维度,以自然人为例,用户个体的敏感字段包括:姓名、身份证号、手机号、邮箱地址等等;在银行系统,作为客户,可能还涉及银行卡号、过期时间、支付密码等等;在公司系统,作为员工,可能还涉及薪资、教育背景等;在医疗系统,作为患者,可能还涉及就诊信息等等。所以,识别和梳理具体业务场景的敏感字段,是创建脱敏策略的第二步。 产品内置一系列常见的脱敏函数接口,可以针对不同数据类型和数据特征,指定参数,从而达到不一样的脱敏效果。脱敏函数可采用如下三种内置接口,同时支持自定义脱敏函数。三种内置脱敏函数能够涵盖大部分场景的脱敏效果,不推荐使用自定义脱敏函数。MASK_NONE:不作脱敏处理,仅内部测试用。MASK_FULL:全脱敏成固定值。MASK_PARTIAL:使用指定的脱敏字符对脱敏范围内的内容做部分脱敏。 不同脱敏列可以采用不同的脱敏函数。比如,手机号通常显示后四位尾号,前面用"*"替换;金额统一显示为固定值0,等等。确定脱敏列需要绑定的脱敏函数,是创建脱敏策略的第三步。 以某公司员工表emp,表的属主用户alice以及用户matu、july为例,简单介绍数据脱敏的使用过程。其中,表emp包含员工的姓名、手机号、邮箱、发薪卡号、薪资等隐私数据,用户alice是人力资源经理,用户matu和july是普通职员。 假设表、用户及用户对表emp的查看权限均已就绪。创建脱敏策略mask_emp,仅允许alice查看员工所有信息,matu和july对发薪卡号、薪资均不可见。字段card_no是数值类型,采用MASK_FULL全脱敏成固定值0;字段card_string是字符类型,采用MASK_PARTIAL按指定的输入输出格式对原始数据作部分脱敏;字段salary是数值类型,采用数字9部分脱敏倒数第二位前的所有数位值。postgres=# CREATE REDACTION POLICY mask_emp ON emp WHEN (current_user != 'alice') ADD COLUMN card_no WITH mask_full(card_no), ADD COLUMN card_string WITH mask_partial(card_string, 'VVVVFVVVVFVVVVFVVVV','VVVV-VVVV-VVVV-VVVV','#',1,12), ADD COLUMN salary WITH mask_partial(salary, '9', 1, length(salary) - 2); 切换到matu和july,查看员工表emp。postgres=>SET ROLE matu PASSWORD 'Gauss@123'; postgres=>SELECT * FROM emp; id | name | phone_no | card_no | card_string | email | salary | birthday ----+------+-------------+---------+---------------------+----------------------+------------+--------------------- 1 | anny | 13420002340 | 0 | ####-####-####-1234 | smithWu@163.com | 99999.9990 | 1999-10-02 00:00:00 2 | bob | 18299023211 | 0 | ####-####-####-3456 | 66allen_mm@qq.com | 9999.9990 | 1989-12-12 00:00:00 3 | cici | 15512231233 | | | jonesishere@sina.com | | 1992-11-06 00:00:00 (3 rows) postgres=>SET ROLE july PASSWORD 'Gauss@123'; postgres=>SELECT * FROM emp; id | name | phone_no | card_no | card_string | email | salary | birthday ----+------+-------------+---------+---------------------+----------------------+------------+--------------------- 1 | anny | 13420002340 | 0 | ####-####-####-1234 | smithWu@163.com | 99999.9990 | 1999-10-02 00:00:00 2 | bob | 18299023211 | 0 | ####-####-####-3456 | 66allen_mm@qq.com | 9999.9990 | 1989-12-12 00:00:00 3 | cici | 15512231233 | | | jonesishere@sina.com | | 1992-11-06 00:00:00 (3 rows) 2. 由于工作调整,matu进入人力资源部参与公司招聘事宜,也对员工所有信息可见,修改策略生效条件。postgres=>ALTER REDACTION POLICY mask_emp ON emp WHEN(current_user NOT IN ('alice', 'matu')); 切换到用户matu和july,重新查看员工表emp。postgres=>SET ROLE matu PASSWORD 'Gauss@123'; postgres=>SELECT * FROM emp; id | name | phone_no | card_no | card_string | email | salary | birthday ----+------+-------------+------------------+---------------------+----------------------+------------+--------------------- 1 | anny | 13420002340 | 1234123412341234 | 1234-1234-1234-1234 | smithWu@163.com | 10000.0000 | 1999-10-02 00:00:00 2 | bob | 18299023211 | 3456345634563456 | 3456-3456-3456-3456 | 66allen_mm@qq.com | 9999.9900 | 1989-12-12 00:00:00 3 | cici | 15512231233 | | | jonesishere@sina.com | | 1992-11-06 00:00:00 (3 rows) postgres=>SET ROLE july PASSWORD 'Gauss@123'; postgres=>SELECT * FROM emp; id | name | phone_no | card_no | card_string | email | salary | birthday ----+------+-------------+---------+---------------------+----------------------+------------+--------------------- 1 | anny | 13420002340 | 0 | ####-####-####-1234 | smithWu@163.com | 99999.9990 | 1999-10-02 00:00:00 2 | bob | 18299023211 | 0 | ####-####-####-3456 | 66allen_mm@qq.com | 9999.9990 | 1989-12-12 00:00:00 3 | cici | 15512231233 | | | jonesishere@sina.com | | 1992-11-06 00:00:00 (3 rows) 3. 员工信息phone_no、email和birthday也是隐私数据,更新脱敏策略mask_emp,新增三个脱敏列。postgres=>ALTER REDACTION POLICY mask_emp ON emp ADD COLUMN phone_no WITH mask_partial(phone_no, '*', 4); postgres=>ALTER REDACTION POLICY mask_emp ON emp ADD COLUMN email WITH mask_partial(email, '*', 1, position('@' in email)); postgres=>ALTER REDACTION POLICY mask_emp ON emp ADD COLUMN birthday WITH mask_full(birthday); 切换到用户july,查看员工表emp。postgres=>SET ROLE july PASSWORD 'Gauss@123'; postgres=>SELECT * FROM emp; id | name | phone_no | card_no | card_string | email | salary | birthday ----+------+-------------+---------+---------------------+----------------------+------------+--------------------- 1 | anny | 134******** | 0 | ####-####-####-1234 | ********163.com | 99999.9990 | 1970-01-01 00:00:00 2 | bob | 182******** | 0 | ####-####-####-3456 | ***********qq.com | 9999.9990 | 1970-01-01 00:00:00 3 | cici | 155******** | | | ************sina.com | | 1970-01-01 00:00:00 (3 rows) 4. 考虑用户交互的友好性,GaussDB (DWS) 提供系统视图redaction_policies和redaction_columns,方便用户直接查看更多脱敏信息。postgres=>SELECT * FROM redaction_policies; object_schema | object_owner | object_name | policy_name | expression | enable | policy_description ---------------+--------------+-------------+-------------+-----------------------------------+--------+-------------------- public | alice | emp | mask_emp | ("current_user"() NOT IN ('alice'::name, 'matu'::name)) | t | (1 row) postgres=>SELECT object_name, column_name, function_info FROM redaction_columns; object_name | column_name | function_info -------------+-------------+------------------------------------------------------------------------------------------------------- emp | card_no | mask_full(card_no) emp | card_string | mask_partial(card_string, 'VVVVFVVVVFVVVVFVVVV'::text, 'VVVV-VVVV-VVVV-VVVV'::text, '#'::text, 1, 12) emp | email | mask_partial(email, '*'::text, 1, "position"(email, '@'::text)) emp | salary | mask_partial(salary, '9'::text, 1, (length((salary)::text) - 2)) emp | birthday | mask_full(birthday) emp | phone_no | mask_partial(phone_no, '*'::text, 4) (6 rows) 5. 突然某一天,公司内部可共享员工信息时,直接删除表emp的脱敏策略mask_emp即可。postgres=# DROP REDACTION POLICY mask_emp ON emp;更多用法详情,请参考GaussDB (DWS) 8.1.1产品文档。数据脱敏实现背后的秘密 GaussDB (DWS)数据脱敏功能,基于SQL引擎既有的实现框架,在受限用户执行查询语句过程中,实现外部不感知的实时脱敏处理。关于其内部实现,如上图所示。我们将脱敏策略(Redaction Policy)视为表对象上绑定的规则,在优化器查询重写阶段,遍历Query Tree中TargetList的每个TargetEntry,如若涉及基表的某个脱敏列,且当前脱敏规则生效(即满足脱敏策略的生效条件且enable开启状态),则断定此TargetEntry中涉及要脱敏的Var对象,此时,遍历脱敏列系统表pg_redaction_column,查找到对应脱敏列绑定的脱敏函数,将其替换成对应的FuncExpr即可。经过上述对Query Tree的重写处理,优化器会自动生成新的执行计划,执行器遵照新的计划执行,查询结果将对敏感数据做脱敏处理。 带有数据脱敏的语句执行,相较于原始语句,增加了数据脱敏的逻辑处理,势必会给查询带来额外的开销。这部分开销,主要受表的数据规模、查询目标列涉及的脱敏列数、脱敏列采用的脱敏函数三方面因素影响。 针对简单查询语句,以tpch表customer为例,针对上述因素展开测试,如下图所示。 图(a)、(b)中基表customer根据字段类型和特征,既有采用MASK_FULL脱敏函数的,也有采用MASK_PARTIAL脱敏函数的。MASK_FULL对于任何长度和类型的原始数据,均只脱敏成固定值,所以,输出结果相较于原始数据,差异很大。图(a)显示不同数据规模下,脱敏和非脱敏场景简单查询语句的执行耗时。实心图标为非脱敏场景,空心图标为被限制用户,即脱敏场景。可见,数据规模越大,带有脱敏的查询耗时与原始语句差异越大。图(b)显示10x数据规模下查询涉及脱敏列数不同对于语句执行性能的影响。涉及1列脱敏列时,带有脱敏的查询比原始语句慢,追溯发现,此列采用的是MASK_PARTIAL部分脱敏函数,查询结果只是改变了结果的格式,结果内容的长度并未变化,符合“带有脱敏的语句执行会有相应的性能劣化”的理论猜想。随着查询涉及脱敏列数的增加,我们发现一个奇怪的现象,脱敏场景反倒比原始语句执行更快。进一步追溯多列场景下脱敏列关联的脱敏函数,发现,正是因为存在使用MASK_FULL全脱敏函数的脱敏列,导致输出结果集部分相比原始数据节省很多时间开销,从而多列查询下带有数据脱敏的简单查询反倒提速不少。 为了佐证上述猜测,我们调整脱敏函数,所有脱敏列均采用MASK_PARTIAL对原始数据做部分脱敏,从而能够在脱敏结果上保留原始数据的外部可读性。于是,如图(c)所示,当脱敏列均关联部分脱敏函数时,带有数据脱敏的语句比原始语句劣化10%左右,理论上讲,这种劣化是在可接受范围的。上述测试仅针对简单的查询语句,当语句复杂到带有聚集函数或复杂表达式运算时,可能这种性能劣化会更明显。总结GaussDB (DWS)产品数据脱敏功能,是数据库产品内化和夯实数据安全能力的重要技术突破,主要涵盖以下三个方面:一套简单、易用的数据脱敏策略语法;一系列可覆盖常见隐私数据脱敏效果的、灵活配置的内置脱敏函数;一个完备、便捷的脱敏策略应用方案,使得原始语句在执行过程中可以实时、透明、高效地实现脱敏。总而言之,此数据脱敏功能可以充分满足客户业务场景的数据脱敏诉求,支持常见隐私数据的脱敏效果,实现敏感数据的可靠保护。【温馨提示】使用过程中,如有疑问,欢迎随时交流反馈。
-
【摘要】 配置SQL ON OBS桶策略,实现DWS访问分离详情请点击博文链接:https://bbs.huaweicloud.com/blogs/246157
-
【摘要】 通过GaussDB(DWS)访问OBS桶获取数据的配置步骤详情请点击博文链接:https://bbs.huaweicloud.com/blogs/228048
-
【摘要】 摘要GTM作为MPPDB集群服务重要组件,主要负责分发xid和snapshot以及sequence,保证系统中全局事务的一致性。序列Sequence是用来产生唯一整数的数据库对象。序列的值是按照一定规则自增的整数。因为自增所以不重复,因此说Sequence具有唯一标识性详情请点击博文链接:https://bbs.huaweicloud.com/blogs/180833
-
【GaussDB(DWS)实践系列】数据倾斜检查与修改方法 数据倾斜排查数据倾斜可通过PGXC_GET_TABLE_SKEWNESS系统表检查:SELECT * FROM PGXC_GET_TABLE_SKEWNESS ORDER BY SKEWRATIO DESC;参考:倾斜率skewratio * DN 数 >0.1 可以判定为倾斜,大小超过5G的表需要处理。实际表数量较多,可参考skewratio> 0.1且大小超过1G,按照倾斜率倒序排列后再处理。 PGXC_GET_TABLE_SKEWNESS视图字段信息如下:名称类型描述schemanamename表所在的模式名。tablenamename表名。totalsizenumeric表的总大小,单位Byte。avgsizenumeric(1000,0)表大小平均值(totalsize/DN个数,该值为平均分布的理想情况下,表在各DN占用空间大小)。maxrationumeric(4,3)单DN表大小最大值占比(表在各DN占用空间的最大值/totalsize)。minrationumeric(4,3)单DN表大小最小值占比(表在各DN占用空间的最小值/totalsize)。skewsizebigint表分布倾斜值(单DN表大小最大值 - 单DN表大小最小值)。skewrationumeric(4,3)表分布倾斜率(skewsize/totalsize)。skewstddevnumeric(1000,0)表分布标准方差(在表大小一定的情况下,该值越大表明表的整体分布情况越倾斜)。hash列选取遵循:数据重复度低(如主键)、常用于group 、join的字段,不会被update的字段(分布列不支持update)。数据倾斜解决范例(更换hash 列) 修改范例 t1 表比如已经创建 需要修改分布列。 t1 表表结构 CREATE TABLE t1 ( c1 int, c2 int )DISTRIBUTE BY HASH(c1); 1. 创建新表,分布列使用c2 CREATE TABLE t1_new ( c1 int, c2 int )DISTRIBUTE BY HASH(c2); 上面可以参考这样写,会更简单 create table t1_new distribute by hash(c2) (like t1 including indexes); 2. 对原表进行 rename,防止数据继续修改。 alter table t1 rename to t1_old; 3. 数据放入新表中 insert into t1_new select * from t1_old; 4. 将新表名称修改为实际表名 alter table t1_new rename to t1; 5. 没问题后删除备份表 drop table t1_old;
-
由于TD和GaussDB(DWS)平台对于char字符进行拼接的结果不一致,即可能导致数据结果不一致;即TD拼接时,会补齐右空格,而GaussDB(DWS)移除右空格拼接;− Teradata:Select cast(‘a’ as char(3))||’b’;返回结果:’a b’− GaussDB(DWS):Select cast(‘a’ as char(3))||’b’;返回结果:’ab’当前建议:TD和GS同时使用rpad改写: select rpad( <char类型字段>, <填充长度,或直接用length(字段)>) from xxxx;
-
TD:Select 1024**3;DWS:Select 1024^3;
-
【操作步骤&问题现象】
-
全文检索(Text search)顾名思义,就是在给定的文档中查找指定模式(pattern)的过程。GaussDB(DWS)支持对表格中文本类型的字段及字段的组合做全文检索,找出能匹配给定模式的文本,并以用户期望的方式将匹配结果呈现出来。本文结合笔者的经验和思考,对GaussDB(DWS)的全文检索功能作简要介绍,希望能对读者有所帮助。 1. 预处理 在指定的文档中查找一个模式有很多种办法,例如可以用grep命令搜索一个正则表达式。理论上,对数据库中的文本字段也可以用类似grep的方式来检索模式,GaussDB(DWS)中就可以通过关键字“LIKE”或操作符“~”来匹配字符串。但这样做有很多问题。首先对每段文本都要扫描,效率比较低,难以衡量“匹配度”或“相关度”。而且只能机械地匹配字符串,缺少对语法语义的分析能力,例如对英语中的名词复数,动词的时态变换等难以自动地识别和匹配,对于由自然语言构成的文本无法获得令人满意的检索结果。 GaussDB(DWS)采用类似搜索引擎的方式来进行全文检索。首先对给定的文本和模式做预处理,包括从一段文本中提取出单词或词组,去掉对检索无用的停用词(stop word),对变形后的单词做标准化等等,使之变为适合检索的形式再作匹配。 GaussDB(DWS)中,原始的文档和搜索条件都用文本(text)表示,或者说,用字符串表示。经过预处理后的文档变为tsvector类型,通过函数to_tsvector来实现这一转换。例如,postgres=# select to_tsvector('a fat cat ate fat rats'); to_tsvector ----------------------------------- 'ate':4 'cat':3 'fat':2,5 'rat':6(1 row) 观察上面输出的tsvector类型,可以看到to_tsvector的效果:首先各个单词被摘取出来,其位置用整数标识出来,例如“fat”位于原始句子中的第2和第5个词的位置。此外,“a”这个词太常见了,几乎每个文档里都会出现,对于检索到有用的信息几乎没有帮助。套用香农理论,一个词出现的概率越大,其包含的信息量越小。像“a”,“the”这种单词几乎不携带任何信息,所以被当做停用词(stop word)去掉了。注意这并没有影响其他词的位置编号,“fat”的位置仍然是2和5,而不是1和4。另外,复数形式的“rats”被换成了单数形式“rat”。这个操作被称为标准化(Normalize),主要是针对西文中单词在不同语境中会发生的变形,去掉后缀保留词根的一种操作。其意义在于简化自然语言的检索,例如检索“rat”时可以将包含“rat”和“rats”的文档都检索出来。被标准化后得到的单词称为词位(lexeme),比如“rat”。而原始的单词被称为语言符号(token)。 将一个文档转换成tsvector形式有很多好处。例如,可以方便地创建索引,提高检索的速度和效率,当文档数量巨大时,通过索引来检索关键字比grep这种全文扫描匹配要快得多。再比如,可以对不同关键字按重要程度分配不同的权重,方便对检索结果进行排序,找出相关度最高的文档等等。 经过预处理后的检索条件被转换成tsquery类型,可通过to_tsquery函数实现。例如,postgres=# select to_tsquery('a & cats & rat'); to_tsquery --------------- 'cat' & 'rat'(1 row) 从上面的例子可以看到:跟to_tsvector类似,to_tsquery也会对输入文本做去掉停用词、标准化等操作,例如去掉了“a”,把“cats”变成“cat”等。输入的检索条件本身必须用与(&)、或(|)、非(!)操作符连接,例如下面的语句会报错postgres=# select to_tsquery('cats rat');ERROR: syntax error in tsquery: "cats rat"CONTEXT: referenced column: to_tsquery 但plainto_tsquery没有这个限制。plainto_tsquery会把输入的单词变成“与”条件:postgres=# select plainto_tsquery('cats rat'); plainto_tsquery----------------- 'cat' & 'rat'(1 row)postgres=# select plainto_tsquery('cats,rat'); plainto_tsquery----------------- 'cat' & 'rat'(1 row) 除了用函数之外,还可以用强制类型转换的方式将一个字符串转换成tsvector或tsquery类型,例如postgres=# select 'fat cats sat on a mat and ate a fat rat'::tsvector; tsvector ----------------------------------------------------- 'a' 'and' 'ate' 'cats' 'fat' 'mat' 'on' 'rat' 'sat'(1 row)postgres=# select 'a & fat & rats'::tsquery; tsquery ---------------------- 'a' & 'fat' & 'rats'(1 row) 跟函数的区别是强制类型转换不会去掉停用词,也不会作标准化,且对于tsvector类型不会记录词的位置。 2. 模式匹配 把输入文档和检索条件转换成tsvector和tsquery之后,就可以进行模式匹配了。GaussDB(DWS)中使用“@@”操作符来进行模式匹配,成功返回True,失败返回false。 例如创建如下表格,postgres=# create table post(postgres(# id bigint,postgres(# author name,postgres(# title text,postgres(# body text);CREATE TABLE-- insert some tuples 然后想检索body中含有“physics”或“math”的帖子标题,可以用如下的语句来查询:postgres=# select title from post where to_tsvector(body) @@ to_tsquery('physics | math'); title ----------------------------- The most popular math books 也可以将多个字段组合起来查询:postgres=# select title from post where to_tsvector(title || ' ' || body) @@ to_tsquery('physics | math'); title ----------------------------- The most popular math books(1 row) 注意不同的查询方式可能产生不同的结果。例如下面的匹配不成功,因为::tsquery没对检索条件做标准化,前面的tsvector里找不到“cats”这个词:postgres=# select to_tsvector('a fat cat ate fat rats') @@ 'cats & rat'::tsquery; ?column?---------- f(1 row) 而同样的文档和检索条件,下面的匹配能成功,因为to_tsquery会把“cats”变成“cat”:postgres=# select to_tsvector('a fat cat ate fat rats') @@ to_tsquery('cats & rat'); ?column?---------- t(1 row) 类似地,下面的匹配不成功,因为to_tsvector会把停用词a去掉:postgres=# select to_tsvector('a fat cat ate fat rats') @@ 'cat & rat & a'::tsquery; ?column?---------- f(1 row) 而下面的能成功,因为::tsvector保留了所有词:postgres=# select 'a fat cat ate fat rats'::tsvector @@ 'cat & rat & a'::tsquery; ?column?---------- f(1 row) 所以应根据需要选择合适的检索方式。 此外,@@操作符可以对输入的text做隐式类型转换,例如,postgres=# select title from post where body @@ 'physics | math'; title-------(0 rows) 准确来讲,text@@text相当于to_tsvector(text) @@ plainto_tsquery(text),因此上面的匹配不成功,因为plainto_tsquery会把或条件'physics | math'变成与条件'physic' & 'math'。使用时要格外小心。 3. 创建和使用索引 前文提到,逐个扫描表中的文本字段缓慢低效,而索引查找能够提高检索的速度和效率。GaussDB(DWS)支持用通用倒排索引GIN(Generalized Inverted Index)进行全文检索。GIN是搜索引擎中常用的一种索引,其主要原理是通过关键字反过来查找所在的文档,从而提高查询效率。可通过以下语句在text类型的字段上创建GIN索引:postgres=# create index post_body_idx_1 on post using gin(to_tsvector('english', body));CREATE INDEX 注意这里必须使用to_tsvector函数生成tsvector,不能使用强制或隐式类型转换。而且这里用到的to_tsvector函数比前一节多了一个参数’english’,这个参数是用来指定文本搜索配置(Text search Configuration)的。关于文本搜索配置将在下一节介绍。不同的配置计算出来的tsvector不同,生成的索引自然也不同,所以这里必须明确指定,而且在查询的时候只有配置和字段都与索引定义一致才能通过索引查找。例如下面的查询中,前一个可以通过post_body_idx_1来检索,后一个找不到对应的索引,只能通过全表扫描检索。postgres=# explain select title from post where to_tsvector('english', body) @@ to_tsquery('physics | math'); QUERY PLAN ----------------------------------------------------------------------------------------------------- id | operation | E-rows | E-width | E-costs ----+---------------------------------+--------+---------+--------- 1 | -> Streaming (type: GATHER) | 1 | 32 | 42.02 2 | -> Bitmap Heap Scan on post | 1 | 32 | 16.02 3 | -> Bitmap Index Scan | 1 | 0 | 12.00 postgres=# explain select title from post where to_tsvector('french', body) @@ to_tsquery('physics | math'); QUERY PLAN ---------------------------------------------------------------------------------------------- id | operation | E-rows | E-width | E-costs ----+------------------------------+--------+---------+------------------ 1 | -> Streaming (type: GATHER) | 1 | 32 | 1000000002360.50 2 | -> Seq Scan on post | 1 | 32 | 1000000002334.50 4. 全文检索配置(Text search Configuration) 这一节谈谈GaussDB(DWS)如何对文档做预处理,或者说,to_tsvector是如何工作的。 文档预处理大体上分如下三步进行:第一步,将文本中的单词或词组一个一个提取出来。这项工作由解析器(Parser)或称分词(Segmentation)器来进行。完成后文档变成一系列token。第二步,对上一步得到的token做标准化,包括依据指定的规则去掉前后缀,转换同义词,去掉停用词等等,从而得到一个个词位(lexeme)。这一步操作依据词典(Dictionary)来进行,也就是说,词典定义了标准化的规则。最后,记录各个词位的位置(和权重),从而得到tsvector。 从上面的描述可以看出,如果给定了解析器和词典,那么文档预处理的规则也就确定了。在GaussDB(DWS)中,这一整套文档预处理的规则称为全文检索配置(Text search Configuration)。全文检索配置决定了匹配的结果和质量。 如下图所示,一个全文检索配置由一个解析器和一组词典组成。输入文档首先被解析器分解成token,然后对每个token逐个词典查找,如果在某个词典中找到这个token,就按照该词典的规则对其做Normalize。有的词典做完Normalize后会将该token标记为“已处理”,这样后面的字典就不会再处理了。有的词典做完Normalize后将其输出为新的token交给后面的词典处理,这样的词典称为“过滤型”词典。 图1 文档预处理过程 配置使用的解析器在创建配置的时候指定,且不可修改,例如,postgres=# create text search configuration mytsconf (parser = default);CREATE TEXT SEARCH CONFIGURATION GaussDB(DWS)内置了4种解析器,目前不支持自定义解析器。postgres=# select prsname from pg_ts_parser; prsname ---------- default ngram pound zhparser(4 rows) 词典则通过ALTER TEXT SEARCH CONFIGURATION命令来指定,例如postgres=# alter text search configuration mytsconf add mapping for asciiword with english_stem,simple;ALTER TEXT SEARCH CONFIGURATION指定了mytsconf使用english_stem和simple这两种词典来对“asciiword”类型的token做标准化。 上面语句中的“asciiword”是一种token类型。解析器会对分解出的token做分类,不同的解析器分类方式不同,可通过ts_token_type函数查看。例如,‘default’解析器将token分为如下23种类型:postgres=# select * from ts_token_type('default'); tokid | alias | description -------+-----------------+------------------------------------------ 1 | asciiword | Word, all ASCII 2 | word | Word, all letters 3 | numword | Word, letters and digits 4 | email | Email address 5 | url | URL 6 | host | Host 7 | sfloat | Scientific notation 8 | version | Version number 9 | hword_numpart | Hyphenated word part, letters and digits 10 | hword_part | Hyphenated word part, all letters 11 | hword_asciipart | Hyphenated word part, all ASCII 12 | blank | Space symbols 13 | tag | XML tag 14 | protocol | Protocol head 15 | numhword | Hyphenated word, letters and digits 16 | asciihword | Hyphenated word, all ASCII 17 | hword | Hyphenated word, all letters 18 | url_path | URL path 19 | file | File or path name 20 | float | Decimal notation 21 | int | Signed integer 22 | uint | Unsigned integer 23 | entity | XML entity(23 rows) 当前数据库中已有的词典可以通过系统表pg_ts_dict查询。 如果指定了配置,系统会按照指定的配置对文档作预处理,如上一节创建GIN索引的命令。如果没指定配置,to_tsvector使用default_text_search_config变量指定的默认配置。postgres=# show default_text_search_config; -- 查看当前默认配置 default_text_search_config---------------------------- pg_catalog.english(1 row)postgres=# set default_text_search_config = mytsconf; -- 设置默认配置SETpostgres=# show default_text_search_config; default_text_search_config---------------------------- public.mytsconf(1 row)postgres=# reset default_text_search_config; -- 恢复默认配置RESETpostgres=# show default_text_search_config; default_text_search_config---------------------------- pg_catalog.english(1 row) 注意default_text_search_config是一个session级的变量,只在当前会话中有效。如果想让默认配置持久生效,可以修改postgresql.conf配置文件中的同名变量,如下图所示。修改后需要重启进程。总结 GaussDB(DWS)的全文检索模块提供了强大的文档搜索功能。相比于用“LIKE”关键字,或 “~”操作符的模式匹配,全文检索提供了较丰富的语义语法支持,能对自然语言文本做更加智能化的处理。配合恰当的索引,能够实现对文档的高效检索。 本文简要介绍了GaussDB(DWS)全文检索的原理和使用方法,关于解析器和词典的更详细的介绍,请看另一篇文章《GaussDB(DWS)全文检索之解析器和词典》(待完成)。
-
针对GaussDB A 集群是支持使用psql对接集群数据库的,当前想知道的是psql的客户端需要在哪获取?
推荐直播
-
华为云码道 × 仓颉编程:工程化AI编码探索2026/05/27 周三 19:00-21:00
刘俊杰-华为云仓颉语言专家/李炎-华为云码道技术专家/王智鹏-OpenCangjie开源社区发起人
本场直播围绕华为云仓颉语言与华为云码道的深度结合,展示华为云智能编程从零基础到高效落地的完整生态能力。以华为云码道为引擎,仓颉语言为载体,带给大家日常提效、趣味创新到极速量产的开发体验。
回顾中
热门标签