• [技术解读] GaussDB关键技术原理:高性能(三)
    GaussDB关键技术原理:高性能(二)从查询处理综述对GaussDB的高性能技术进行了解读,本篇将从查询重写RBO、物理优化CBO、分布式优化器、布式执行框架、轻量全局事务管理GTM-lite等五方面对高性能关键技术进行分享。3 高性能关键技术 内容概要:本章节介绍GaussDB中实现的高性能关键技术,内容涉及优化器、执行器、分布式数据库、存储引擎等多个方面。 目的:通过对GaussDB数据库关键高性能技术的学习,能够让读者更加清晰的理解数据库内核哪些优化是性能关键点同时也为类似的应用系统实现提供方法论和最佳实践。  3.1 查询重写RBO 在数据库里RBO基于规则的优化一般指查询重写技术,按照一系列关系代数表达式的等价规则,对查询的关系代数表达式进行等价转换,从逻辑上减少执行的总量从而提高查询执行效率,例如,通过条件的推导得出非必要的表扫描、避免非必要的计算表示等。    查询重写RBO优化是非常重要的一种逻辑优化手段,通常应用和实施在查询优化过程的前端,将一些肯定能够优化的场景进行优化,RBO优化结束后进行物理优化,以下以常用的几种重写优化进行介绍:  Example 1:谓词化简优化Predicate Simplification  使用谓词查询条件的可满足性Satisfiability (SAT)&可传递性Transitive Closure(TC)对查询进行化简,a.w.k SAT-TC,假设有t1,t2表,他们的定义分别为:T1(c1 int, c2 int);,T2(c1 int, c2 int check (c2 < 30));,则原查询: SELECT t1.c1,t1.c2, t2.c1, t2.c2FROM t1 JOIN t2 ON t1.c2 = t2.c2WHERE t1.c2 > 20可优化为:SELECT dt1.c1,dt1.c2, dt2.c1, dt2.c2FROM (select c1,c2 from t1 where t1.c2 between 20 and 30) as dt1,(select c1,c2 from t2 where t2.c2 between 20 and 30) as dt2WHERE dt1.c2 = dt2.c2;说明:通过谓词逻辑可以发现当前查询中可以一次实施TC->SAT->TC优化策略。  step1: TC优化:内连接关联条件t1.c2 = t2.c2 && t1.c2 > 20可以得出t2.c2 > 20  step2: SAT优化:t2.c2列上创建有check-constraint可以得出t2.c2 BETWEEN 20 AND 30  step3: TC优化:同理得出t1.c2 BETWEEN 20 AND 30  到此t1,t2在关联之前就可以最大限度减小处理的元组数,达到提升性能的目的,以下是其他SATTC例子: ————————————————                              版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 说明:通过谓词逻辑可以发现当前查询中可以一次实施TC->SAT->TC优化策略。  step1: TC优化:内连接关联条件t1.c2 = t2.c2 && t1.c2 > 20可以得出t2.c2 > 20  step2: SAT优化:t2.c2列上创建有check-constraint可以得出t2.c2 BETWEEN 20 AND 30  step3: TC优化:同理得出t1.c2 BETWEEN 20 AND 30  到此t1,t2在关联之前就可以最大限度减小处理的元组数,达到提升性能的目的,以下是其他SATTC例子: ————————————————                              版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                          说明:通过谓词逻辑可以发现当前查询中可以一次实施TC->SAT->TC优化策略。  step1: TC优化:内连接关联条件t1.c2 = t2.c2 && t1.c2 > 20可以得出t2.c2 > 20  step2: SAT优化:t2.c2列上创建有check-constraint可以得出t2.c2 BETWEEN 20 AND 30  step3: TC优化:同理得出t1.c2 BETWEEN 20 AND 30  说明:通过谓词逻辑可以发现当前查询中可以一次实施TC->SAT->TC优化策略。                        step1: TC优化:内连接关联条件t1.c2 = t2.c2 && t1.c2 > 20可以得出t2.c2 > 20  step2: SAT优化:t2.c2列上创建有check-constraint可以得出t2.c2 BETWEEN 20 AND 30  step3: TC优化:同理得出t1.c2 BETWEEN 20 AND 30  到此t1,t2在关联之前就可以最大限度减小处理的元组数,达到提升性能的目的,以下是其他SATTC例子: A=B AND A=C --> B=CA=5 AND A=B --> B=5A=5 AND A IS NULL --> FALSEA=5 AND A IS NOT NULL --> A=5X > 1 AND Y > X --> Y >= 3X IN (1,2,3) AND Y=X --> Y IN (1,2,3)Example 2:谓词下推优化Predicate Push Down将谓词查询条件下沉到中间结果集的最底层提前过滤,可以有效减少读入到内存中数据的数量,减少计算层的代价优化前:SELECT MAX(total)FROM (SELECT product_key, product_name,SUM(quantity*amount) AS totalFROM Sales, ProductWHERE sales_product_key=product_keyGROUP BY product_key, product_name) AS vWHERE product_key IN (10, 20, 30);优化后:SELECT MAX(total)FROM (SELECT product_key, product_name,SUM(quantity*amount) AS totalFROM Sales, ProductWHERE sales_product_key=product_key AND product_key IN (10, 20, 30)GROUP BY product_key, product_name) AS vWHERE product_key IN (10, 20, 30);说明:  查询在优化前需要事先将中间结果集v计算出。  在计算的过程中需要对sales、product两张表的全量数据进行读取进行,然后对结果集进行Group分组、Aggregation聚合操作,但是最终的结果集只要求输出product_key的值为10,20,30的结果集。  利用谓词下推规则可以让product_key in(10,20,30)过滤操作在Join之前完成,如果查询条件product_key in(10,20,30)的选择率较低则可以减少Join、Aggregation、Group三个操作处理的数据量,从而提升性能。  Example 3:谓词上移优化Predicate Pullup  将谓词查询条件中比较繁重的函数计算放到最后,期望减小繁重计算的次数达到提升性能的目的。  优化前: SELECT *FROM t1,(SELECT * FROM t2WHERE complex_func(t2.c2) = 3) AS dt(c1,c2,c3)WHERE t1.c1 = t2.c1 AND t1.c2 > 30优化后:SELECT *FROM t1,(SELECT * FROM t2) AS dt(c1,c2,c3)WHERE t1.c1 = t2.c1 AND t1.c2 > 30 AND complex_func(t2.c2) = 3说明:  原查询“complex_func(t2.c2) = 3”查询条件在子查询中,如果该条件在子查询DT中被计算则会导致t2表中的全量数据被计算开销较大。  通过谓词pullup上移到最外层让t2先和t1做关联和过滤,则能够有效减少complex_func被调用的次数,从而达到性能提升的目的。  查询重写是查询优化器阶主要分类之一,通常可以快速将处理的数据进行成倍数缩减,下图是常见的查询重写分类 3.2 物理优化CBO 在优化器处理完RBO的优化以后,路径的选择往往不能通过实现制定好的规则进行变换,而是需要根据数据的分布(统计信息)情况来对查询执行路径进行评估,从可选的路径中选择一个执行代价最小的路劲进行执行,例如是否选择索引SeqScan vs. IndexScan、选择哪个索引,两表关联选择什么样的连接顺序,选择怎样的具体算法等,因此,可以将物理优化总结为对多个可行的物理执行代价进行评估,选择最优的计划输出到执行器进行执行,例如有以下查询: select * from t1 join t2 on t1.a=t2.b;可选择的计划有:如上图所示,根据T1、T2可访问的执行路径:IndexScan vs. SeqScan,关联算法:HashJoin、MergeJoin、NestLoop;关联内表外表等多个维度的选择,就会生成多达数十种不同的执行计划,由于考虑到T1、T2的表大小,谓词的选择率、是否有索引等因素很难从一个固定的规则里选出一个合理的执行计划,此时需要对T1、T2表的数据特征进行建模,构建代价模型从而选出最优的计划,这个过程按照处理的顺序大体上可以分为:统计信息、行数估算、代价估算、路径搜索、计划生成五个处理步骤:  (1)统计信息,物理优化的依据来源于表信息的统计, 描述基表数据的特征包括唯一值、MCV值等,用于行数估算。  (2)行数估算,代价估算的基础,来源于基表统计信息的推算,估算基表baserel、Join中间结果集joinrel、Aggregation中结果集大小,为代价估算做准备。  (3)代价估算,根据关系的行数,推算出当前算子的执行代价,根据数据量估算不同算子执行代价,各算子代价之和即为计划总代价。  (4)路径搜索,依据若干算子的执行代价对最优路径进行路径搜索,通过求解路径最优算法(e.g. 动态规划、遗传算法)处理连接路径搜索过程,以最小搜索空间找到最优连接路径。  (5)计划生成,将查询的执行路径转换成PlanTree能够输出给执行器做查询执行,在分布式场景下根据数据分布的属性决定Data-Shuffling数据迁移总体方案。  3.3 分布式优化器 分布式数据库场景下表分布在各个节点上,数据的本地性Data Locality是分布式优化器中生成执行计划时重点考虑的因素,基于Share Nothing的分布式数据库中有一个很关键概念就是“移动数据不如移动计算”,之所以有数据本地性就是因为数据在网络中传输会有不小的I/O消耗,网络的overhead通常情况下会大于本地的计算,因此分布式数据库优化的一个重要的原则就是尽量减少这个网络I/O消耗就能够提升效率。例如有以下例子一个聚集查询的例子: 表信息:- T1: distribute By HASH(c1)执行查询:- select sum(c1), c2 from t1 group by c2由于表T1的分布列为c1但实际上要按照c2为键值进行聚集,对聚集列进行重分布是不可避免的一步操作,因此先做聚集还是先做数据迁移重分布就成为分布式优化器的一个选项,针对这一情况可以有以下两种分布式执行计划选择:说明:  (1)执行计划A未考虑Data Locality的优化按照聚集的逻辑直接从扫描输出的100m元组进行重分布操作,造成大量的数据传输和网络资源消耗。  (2)执行计划B考虑Data Locality的优化,把AGG算子分解成2次AGG,其中第一次AGG在本地执行对原始数据进行缩减然后再通过网络重分布进入第二次AGG,虽说执行计划B相比A多了1个AGG算子,尽管计算的总量未发生变化但是节省了大量的网络IO操作,端到端提升了查询性能。  表关联也是类似的原理,如果当join列与分布列不一致时,需要网络stream节点算子对数据进行重分布或者复制确保查询执行的语义正确。  3.4 分布式执行框架 由于GaussDB采用的是无共享Shared-nothing的架构,由众多独立且互不共享CPU、内存、存储等系统资源的逻辑节点组成。在这样的系统架构中,业务数据被分散存储在多个物理节点上,数据分析任务会被推送到数据所在位置就近执行,通过控制模块的协调,并行地完成大规模的数据处理工作,实现对数据处理的快速响应。DN是基于本节点存储的数据执行具体的执行计划;DN之间可能会有数据交互,这个数据交互就通过分布式执行框架来完成。分布式框架主要靠网络通信算子Steram完成,Stream算子是分布式执行框架的核心元素,Stream算子主要有2个职责:(1)数据重分布(Data Shuffling):负责将单节点DataNode进程串联成为分布式集群的能力也就是通常理解的数据重分布,其他友商如GreemPlum的Motion节点,VectorWise的DXchg节点也具备类似的功能;(2)分布式流水线(Distribute Pipeline):将原有的分布式执行计划进行并行切分,即以Stream节点作为处理流水线分界由不同的工作线程完成,线程间以PV生产者消费者模式工作,  数据重分布(Data Shuffling)  针对当前GaussDB所支持的数据重分布机制上有3种工作模式:  (1)Gather Stream(N:1)每个源节点都将其数据发送给目标节点,一般用于汇总DN节点到CN节点的过程。 (2)Redistribute Stream(M:N):M个DN节点将其数据根据关联条件、聚集分组表达式算出Hash值,根据重新计算的Hash值进行分布,发送数据到对应的目标节点。一般用于Join、Agg、NodeGroup中的重分布场景。(3)Broadcast Stream(1:N):有一个源节点将其数据发给N个目标节点。例如下图的分布式执行计划,由于不同的表分布属性不同,因此通过分布式执行框架Stream节点进行数据串联并执行,最后在CN节点进行结果集汇总。说明:  (1)执行的过程中对T1、T2的扫描都在DN节点上并行完成。  (2)优化器生成的执行计划选择了前一节中描述的方案3,即T1保持不动复制T2到所有节点,并完成分布式HASHJOIN。  (3)HashJoin节点在所有节点上执行完成以后通过Gather节点在CN上进行结果集汇总。  分布式执行流水线(Distribution Pipeline)  在分布式执行过程中如果存在数据搬移,Stream算子的数据发送端、数据接收端有不同的线程完成,他们在时间分片上重叠以并行的方式执行,因此全局执行计划被网络通信算子Stream切分成多个计划片段,分别有不同的线程来完成执行,不同的线程之间采用PC生产者消费者进行交互通信,全局上达到并行执行的效果。如下图,实际的计划执行在DN这一层以Stream算子为界,被切分成多个线程并行处理。 3.5 轻量全局事务管理GTM-lite GTM,全称Global Transaction Manager,即全局事务管理器,负责全局事务号的分发,事务提交时间戳的分发以及全局事务运行状态的登记,作为事务管理中的重要模块,为支持事务一致性提供必要的保证。事务开始和提交时与GTM进行交互获取必要的全局事务信息,包括事务ID,全局时间戳,全局快照等等。与其他模块一个很重要的不同点就是,为了保证一致性和事务标识全局唯一,集群中只要一个主GTM,即只有一个GTM真正参与事务(不过GTM和DN一样是高可用的,支持一主多备或主备从)。使用GTM来进行事务管理,一个很重要的问题就是会出现单点瓶颈,因为所有需要获取事务唯一标识的事务都需要连接GTM,获取全局快照的时候也都需要连接GTM,在大并发的情况下频繁的交互导致大量的网络通信和锁等待,从而限制了集群性能。  在老的GTM模式下,虽然通过将活跃事务链表替换为CSN来减少了通信量,但是由于仍采用全局事务id的策略,所以每个活跃事务仍要在GTM注册槽位,GTM负责管理和分发全局事务id,这导致当并发量大的时候,GTM容易成为单点瓶颈,主要体现在以下两个方面:  (1)在一个事务的执行流程中,CN会与GTM进行多次交互,如事务开始时在GTM注册槽位、获取快照时从GTM获取全局事务id、事务结束时向GTM提交并移除槽位等,这些频繁的交互会带来大量的网络通信和等待;  (2)当并发量超过槽位数限制时,会由于槽位不够影响业务正常进行。  由此可见,其影响性能的主要原因在于GTM的协调太强,通过对全局事务id的管控,虽然保证了事务的一致性,但是也限制了事务处理的效率。与GTM模式相反,GTM-FREE模式下CN/DN不与GTM交互,通过CN/DN分别维护本地事务id来保证事务系统的正常运行。这种模式下由于缺少全局事务id以及GTM的其他协调(CSN),事务的一致性会受到影响,从而限制了这种模式的适用范围。综上,现有的两种模式在效率和一致性要求上并没有达到一个很好的平衡,而影响这种平衡的主要因素在与“协调”,协调带来更多一致性的保障,但是却降低了性能。由此,一个好的模式应该是在尽可能少的协调的情况下,达到尽可能高的性能,这也是本章介绍的GTM-LITE模式  GTM-LITE的主要目标就是在消除GTM瓶颈影响的同时,尽可能通过更少的信息交互,利用它来协调好事务的并发,从而保证事务一致性的同时提升性能。为此,GTM-LITE的主要设计思路包含以下4点:  (1)本地事务id取代全局事务id。GTM不再分配全局唯一的事务id,每个CN/DN节点用本地产生的事务id,保证节点内事务id不会重复;对于跨节点的事务,由全局唯一的gid标识符前缀来保证写一致性,由全局唯一的csn号来保证事务读的一致性。  (2)GTM不再维护槽位信息,仅在事务提交时下发全局唯一的csn序列号。GTM下发的全局csn是一个递增的uint64值。这一设计消除了BEGIN, GetNewTransactionId同GTM的交互。进一步,如果事务在GTM提交时失败,可以retry重新获取最新的csn,减少网络故障对系统造成的影响。  (3)本地维护多版本过期脏元组的回收,并引入Snapshot Invalid机制,保证全局事务的一致性。由于舍弃全局事务id,无法直接根据RecentGlobalXmin确定需要清理的脏元组,所以需要利用全局csn来计算RecentGlobalXmin,从而实现GTM架构代码的有效复用。  (4)引入prepared array链表对单节点事务可见性判断进行优化。对于单节点的读事务,不再向GTM申请快照,而是使用本地的快照+prepared array链表来进行可见性判断,这种方式在保证读外部一致性的前提下,尽可能的减少同GTM的交互。基本判断方法为:对于csn<本地快照csn的事务以及本地prepared(在prepared array中)且最终提交的事务,均可见。  以上内容从查询重写RBO、物理优化CBO、分布式优化器、布式执行框架、轻量全局事务管理GTM-lite等五方面对高性能关键技术的进行了分享,下篇将从USTORE存储引擎、计划缓存计划技术、数据分区与分区剪枝、列式存储和向量化引擎、SMP并行执行等方面继续解读高性能关键技术,敬请期待! 
  • [技术干货] GaussDB 技术干货集合
    序号网址标题1https://bbs.huaweicloud.com/forum/thread-0235152777783711058-1-1.htmlGaussDB数据库如何创建修改数据库和数据表2https://bbs.huaweicloud.com/forum/thread-0235152777783711058-1-1.htmlGaussDB数据库如何创建修改数据库和数据表3https://bbs.huaweicloud.com/forum/thread-0272151812820406012-1-1.htmlGaussDB数据库的元数据及其管理简介4https://bbs.huaweicloud.com/forum/thread-02109151812652385008-1-1.htmlGaussDB的行存表与列存表的选择5https://bbs.huaweicloud.com/forum/thread-0299151812618135019-1-1.htmlGaussDB云数据库配套工具UGO6https://bbs.huaweicloud.com/forum/thread-02120151812519215014-1-1.htmlGaussDB OLTP 云数据库配套工具DAS7https://bbs.huaweicloud.com/forum/thread-02109151812463028007-1-1.htmlGaussDB OLTP云数据库配套工具DRS8https://bbs.huaweicloud.com/forum/thread-02119151812405488013-1-1.htmlGaussDB OLTP云数据库配套工具DDM9https://bbs.huaweicloud.com/forum/thread-0236151812356015011-1-1.html数据库模型设计案例分享(GaussDB版)10https://bbs.huaweicloud.com/forum/thread-02106149253127739038-1-1.htmlGaussDB 常用语法总结【操作指导集合】11https://bbs.huaweicloud.com/forum/thread-02107149218966585035-1-1.htmlGaussDB数据库SQL系列-聚合函数12https://bbs.huaweicloud.com/forum/thread-02106149217197091032-1-1.html由数据插入超长引起的问题——了解GaussDB和openGauss的字符集13https://bbs.huaweicloud.com/forum/thread-0235152777783711058-1-1.htmlGaussDB数据库如何创建修改数据库和数据表14https://bbs.huaweicloud.com/forum/thread-0272151812820406012-1-1.htmlGaussDB数据库的元数据及其管理简介15https://bbs.huaweicloud.com/forum/thread-02109151812652385008-1-1.htmlGaussDB的行存表与列存表的选择16https://bbs.huaweicloud.com/forum/thread-0299151812618135019-1-1.htmlGaussDB云数据库配套工具UGO17https://bbs.huaweicloud.com/forum/thread-02120151812519215014-1-1.htmlGaussDB OLTP 云数据库配套工具DAS18https://bbs.huaweicloud.com/forum/thread-02109151812463028007-1-1.htmlGaussDB OLTP云数据库配套工具DRS19https://bbs.huaweicloud.com/forum/thread-02119151812405488013-1-1.htmlGaussDB OLTP云数据库配套工具DDM20https://bbs.huaweicloud.com/forum/thread-0236151812356015011-1-1.html数据库模型设计案例分享(GaussDB版)21https://bbs.huaweicloud.com/forum/thread-02106149253127739038-1-1.htmlGaussDB 常用语法总结【操作指导集合】22https://bbs.huaweicloud.com/forum/thread-02107149218966585035-1-1.htmlGaussDB数据库SQL系列-聚合函数23https://bbs.huaweicloud.com/forum/thread-02106149217197091032-1-1.html由数据插入超长引起的问题——了解GaussDB和openGauss的字符集24https://bbs.huaweicloud.com/forum/thread-0297146799368478025-1-1.htmlGaussDB WDR分析之集群报告篇25https://bbs.huaweicloud.com/forum/thread-0231145158414495004-1-1.html利用GaussDB的可观测性能力构建故障模型26https://bbs.huaweicloud.com/forum/thread-0235152777783711058-1-1.htmlGaussDB数据库如何创建修改数据库和数据表27https://bbs.huaweicloud.com/forum/thread-0272151812820406012-1-1.htmlGaussDB数据库的元数据及其管理简介28https://bbs.huaweicloud.com/forum/thread-02109151812652385008-1-1.htmlGaussDB的行存表与列存表的选择29https://bbs.huaweicloud.com/forum/thread-0299151812618135019-1-1.htmlGaussDB云数据库配套工具UGO30https://bbs.huaweicloud.com/forum/thread-02120151812519215014-1-1.htmlGaussDB OLTP 云数据库配套工具DAS31https://bbs.huaweicloud.com/forum/thread-02109151812463028007-1-1.htmlGaussDB OLTP云数据库配套工具DRS32https://bbs.huaweicloud.com/forum/thread-02119151812405488013-1-1.htmlGaussDB OLTP云数据库配套工具DDM33https://bbs.huaweicloud.com/forum/thread-0236151812356015011-1-1.html数据库模型设计案例分享(GaussDB版)34https://bbs.huaweicloud.com/forum/thread-02106149253127739038-1-1.htmlGaussDB 常用语法总结【操作指导集合】35https://bbs.huaweicloud.com/forum/thread-02107149218966585035-1-1.htmlGaussDB数据库SQL系列-聚合函数36https://bbs.huaweicloud.com/forum/thread-02106149217197091032-1-1.html由数据插入超长引起的问题——了解GaussDB和openGauss的字符集37https://bbs.huaweicloud.com/forum/thread-0297146799368478025-1-1.htmlGaussDB WDR分析之集群报告篇38https://bbs.huaweicloud.com/forum/thread-0231145158414495004-1-1.html利用GaussDB的可观测性能力构建故障模型39https://bbs.huaweicloud.com/forum/thread-0284144599249246009-1-1.htmlGaussDBAPI概览40https://bbs.huaweicloud.com/forum/thread-0202142095354960004-1-1.htmlGaussDB数据库:创建高性能索引
  • [技术解读] GaussDB和Postgres
     数据库结构:两者都支持SQL语言和ACID事务,具有相似的数据库结构,包括表、视图、存储过程、触发器等。  开源:两者都是开源软件,均可以免费使用和修改。  数据库安全:两者都提供了安全控制机制,包括用户权限控制、数据加密等。  数据备份和恢复:两者都支持数据备份和恢复,可以保证数据的可靠性和完整性。  但是,GaussDB和Postgres也存在一些不同之处:  数据库架构:GaussDB采用分布式架构,可以支持海量数据存储和高并发访问,而Postgres采用单机架构。  数据库性能:GaussDB具有更高的性能和扩展性,可以支持更大规模的数据处理和更高的并发访问。  数据库功能:GaussDB具有更多的高级功能,如在线数据迁移、在线扩容等,而Postgres则更加注重数据完整性和数据安全性。  总之,GaussDB和Postgres都是优秀的数据库管理系统,可以根据实际需求选择使用。如果需要处理海量数据和高并发访问,可以考虑使用GaussDB 
  • [技术解读] GaussDB分布式和主备的区别
     GaussDB分布式和主备的区别主要在于数据的存储和管理方式以及系统的可用性。  数据存储和管理方式:在主备模式下,数据只存储在主节点上,备节点只是主节点的备份,主节点负责处理所有的数据读写请求,备节点只有在主节点出现故障时才会接管主节点的工作。而在分布式模式下,数据被分成多个分片,存储在不同的节点上,每个节点都可以处理部分数据的读写请求,数据的管理更为分散和灵活。  系统可用性:在主备模式下,当主节点出现故障时,备节点需要接管主节点的工作,但是这个过程需要一定的时间,系统在这段时间内是不可用的。而在分布式模式下,即使某个节点出现故障,其他节点仍然可以处理数据的读写请求,系统的可用性更高。  总的来说,主备模式更适合对数据一致性要求较高、对系统可用性要求相对较低的场景,而分布式模式更适合对系统可用性和数据处理能力要求较高的场景。 
  • [技术解读] GaussDB SQL基础语法示例-GOTO语句
    一、前言SQL是用于访问和处理数据库的标准计算机语言。GaussDB支持SQL标准(默认支持SQL2、SQL3和SQL4的主要特性)。本系列将以《云数据库GaussDB—SQL参考》在线文档为主线进行介绍。GOTO 语句是直观基本的控制流语句,会导致控制流发生无条件更改。它用于分流至使用 SQL 过程中定义的标签的特定用户定义位置。使用 GOTO 语句通常被视为缺乏编程技巧,并且不推荐这样做。大量使用 GOTO 会导致代码可读性不好,特别是在过程变长时。此外,因为有更好的语句可用于控制执行路径,所以 GOTO 并非必需。没有需要使用 GOTO 的特定情况;使用它通常只是为了方便。二、在GaussDB数据库中的概念及语法1、基本概念GOTO语句是一种控制语句,它用于无条件地将程序的执行跳转到指定的位置。在GaussDB数据库的SQL实现中,GOTO语句通常被用于存储过程和触发器等数据库对象中,以实现复杂的逻辑控制。GOTO语句可以实现从GOTO位置到目标语句的无条件跳转。GOTO语句会改变原本的执行逻辑,因此应该慎重使用。当执行GOTO语句时,目标Label必须是唯一的。2、语法BEGIN--some code hereIF condition THENGOTO label;END IF;-- some code hereGOTO label;<<label>>-- code to jump toEND;/三、在GaussDB数据库中的基础示例和限制场景说明1、基础示例创建一个函数,在满足一定条件时,通过GOTO语句进行跳转。CREATE OR REPLACE FUNCTION proc_goto(i in integer,j in integer)RETURNS TEXTLANGUAGE plpgsqlAS $$BEGINLOOPINSERT INTO test_1(id,date) VALUES(i,current_date) ;i := i+1;IF i=j THENGOTO label;END IF;END LOOP;<<label>>INSERT INTO test_1(id,date) VALUES(i,'3000-12-31') ;RETURN 'succeed';END $$;CALL proc_goto(1,5);select * from test_1;2、限制场景说明GOTO使用有以下限制场景:1、不支持有多个相同的GOTO labels目标场景,无论是否在同一个block中。BEGINGOTO label 1;<< label 1>>SELECT * FROM ...<< label 1>>UPDATE t1 SET ...END;2、不支持GOTO跳转到IF语句,CASE语句,LOOP语句中。BEGINGOTO label 1;IF valid THEN<< label 1>>SELECT * FROM ...END IF;END;3、不支持GOTO语句从一个IF子句跳转到另一个IF子句,或从一个CASE语句的WHEN子句跳转到另一个WHEN子句。BEGINIF valid THENGOTO label 1;SELECT * FROM ...ELSE<< label 1>>UPDATE t1 SET ...END IF;END;4、不支持从外部块跳转到内部的BEGIN-END块,即禁止从外层跳转到内层。BEGINGOTO label 1;BEGIN<< label 1>>UPDATE t1 SET ...END;END;5、不支持从异常处理部分跳转到当前的BEGIN-END块。但可以跳转到上层BEGIN-END块。BEGIN<< label 1>>UPDATE t1 SET ...EXCEPTIONWHEN condition THENGOTO label 1;END;6、如果从GOTO到一个不包含执行语句的位置,需要添加NULL语句。DECLAREdone BOOLEAN;BEGINFOR i IN 1..50 LOOPIF done THENGOTO end_loop;END IF;<<end_loop>>NULL;END LOOP;END;/四、小结在本文中,我们介绍了GOTO语句在云数据库GaussDB SQL中的使用特点,通过一系列的示例,可以更好地组织代码,避免一些不必要的计算和操作,从而提高SQL语句的执行效率。 但同时需要注意的是,GOTO语句虽然可以用于实现复杂的逻辑控制,但也容易导致代码的可读性降低和维护困难。因此,在实际开发中,应该根据具体情况慎重使用GOTO语句。——结束
  • [运维管理] 为什么需要每次执行source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile命令启动环境变量。直接写到.bashrc文件里面不行吗?有什么影响和弊端?
    为什么需要每次执行source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile命令启动环境变量。直接写到.bashrc文件里面不行吗?有什么影响和弊端?
  • [技术解读] GaussDB SQL基础语法示例-循环语句
    一、前言SQL是用于访问和处理数据库的标准计算机语言。GaussDB支持SQL标准(默认支持SQL2、SQL3和SQL4的主要特性)。本系列将以《云数据库GaussDB—SQL参考》为主线进行介绍。二、GaussDB数据库总的循环语句在GaussDB数据库中,循环语句是一种常用的控制流语句,用于在数据库查询中执行重复操作。通过使用循环语句,我们可以灵活地处理数据集中的每一行,并根据需要对数据进行转换、过滤或计算。循环语句在处理大规模数据、进行复杂计算和操作时具有显著的优势。在GaussDB数据库中,循环语句主要包括LOOP、WHILE LOOP、FOR LOOP和FORALL等语句。这些语句用于在数据库查询中执行重复操作,并可以根据需要选择合适的循环类型来处理数据集中的每一行。 本文将介绍GaussDB数据库中的循环语句及其应用。三、GaussDB中常用循环语句(语法 + 示例)1、LOOP循环语句LOOP循环是一个无限循环,直到显式地使用EXIT语句退出循环。在循环体内部,可以根据条件执行重复的查询操作。例如,可以使用IF语句在每次循环时检查条件,并执行相应的操作。语法:LOOPstatementsEND LOOP;Tip: 该循环必须要结合EXIT使用,否则将陷入死循环。示例:---插入多条数据,i是字段id起始值,j终止值。CREATE OR REPLACE PROCEDURE proc_loop(i in integer,j in integer)ASBEGINLOOP-- 执行重复的插数操作INSERT INTO test_1(id,c_times) VALUES(i,current_timestamp) ;--id值递增 +1i := i+1;-- 退出循环的条件IF i=j THENEXIT;END IF;END LOOP;END;/CALL proc_loop(1,5);SELECT * FROM test_1;2、WHILE … LOOP 循环语句WHILE … LOOP循环是一个有条件的循环,只要满足指定的条件,循环就会继续执行。在循环体内部,可以执行重复的查询操作。当条件不再满足时,循环会终止。语法:WHILE condition LOOPstatementsEND LOOP;示例:---插入多条数据,i是字段id起始值,j终止值。CREATE OR REPLACE PROCEDURE proc_loop_1(i in integer,j in integer)ASBEGINWHILE i < j LOOP-- 执行重复的查询操作INSERT INTO test_1(id,c_times) VALUES(i,current_timestamp);--id值递增 +1i := i+1;END LOOP;END;/CALL proc_loop_1(5,10);SELECT * FROM test_1;3、FOR … LOOP循环语句(integer变量)FOR LOOP循环是按照指定的次数执行循环。在循环体内部,可以执行重复的查询操作。语法:FOR name IN [REVERSE] lower_bound ..upper_bound [BY step] LOOPstaementsEND LOOP;Tip: 变量name会自动定义为integer类型并且只在此循环里存在。变量name介于lower_bound和upper_bound之间。 当使用REVERSE关键字时,lower_bound必须大于等于upper_bound,否则循环体不会被执行。示例:---插入多条数据,i是字段id起始值,j终止值。CREATE OR REPLACE PROCEDURE proc_loop_2(i in integer,j in integer)ASBEGINFOR i IN i..j LOOP-- 执行重复的查询操作INSERT INTO test_1(id,c_times) VALUES(i,current_timestamp);END LOOP;END;/CALL proc_loop_2(10,15);SELECT * FROM test_1;4、FORALL循环语句(批量查询)FORALL循环是一种并行化的循环,用于在数据集上执行并行操作。它适用于处理大规模数据集,可以利用多核处理器并行执行查询操作。语法:FORALL index IN lower_bound .. upper_bound DML;Tip:变量index会自动定义为integer类型并且只在此循环里存在。index的取值介于low_bound和upper_bound之间。示例:---插入多条数据,CREATE OR REPLACE PROCEDURE proc_loop_3(i in integer,j in integer)ASBEGINFORALL i IN i..j-- 执行重复的查询操作INSERT INTO test_1(id,c_times) VALUES(i,current_timestamp);END;/CALL proc_loop_3(16,20);SELECT * FROM test_1;四、小结本文介绍了GaussDB数据库中的循环语句及其使用方法。循环语句提供了灵活的数据处理能力。通过掌握循环语句的用法,我们可以更好地利用GaussDB数据库的功能,提高数据处理效率和查询性能。——结束
  • [技术解读] GaussDB SQL基础语法-变量&常量
    一、前言SQL是用于访问和处理数据库的标准计算机语言。GaussDB支持SQL标准(默认支持SQL2、SQL3和SQL4的主要特性)。本系列将以《云数据库GaussDB—SQL参考》在线文档为主线进行介绍。二、GaussDB数据库中的常量和变量的基本概述及语法定义数据库中的变量和常量是两种重要的数据使用类型。变量是可以变化和被修改的,而常量则是固定不变,不能被修改的。1、变量定义在GaussDB中,变量是用于存储可变值的数据类型。变量通常在程序中定义,并在执行期间可以更改其值。在GaussDB中,可以使用以下语法来定义变量:DECLARE variable_name data_type;其中,variable_name 是变量的名称,data_type 是变量的数据类型。例如,要定义一个名为 my_variable 的整数变量,可以使用以下语句:DECLARE my_variable INT;2、常量定义在GaussDB中,常量用于存储固定值的数据类型。常量在程序中定义后,其值不能被修改。在GaussDB中,可以使用以下语法来定义常量:DECLARE constant_name data_type = constant_value;其中,constant_name 是常量的名称,data_type 是常量的数据类型,constant_value 是常量的值。例如,要定义一个名为 my_constant 的整数常量,可以使用以下语句:DECLARE my_constant INT = 10;这将定义一个名为 my_constant 的整数常量,其值为 10。请注意,这只是GaussDB中定义变量和常量的基本语法。具体建议参考GaussDB的官方文档或相关资料以获取更详细信息。3、其他(%TYPE、%ROWTYPE属性)变量类型除了支持基本类型,还可使用%TYPE和%ROWTYPE去声明一些与其他表字段或表结构本身相关的变量。%TYPE属性:%TYPE主要用于声明某个与其他变量类型(例如,表中某列的类型)相同的变量。假如我们想定义一个my_name变量,它的变量类型与employee的firstname类型相同,我们可以通过如下定义:--使用某列的属性声明DECLARE my_name employee.firstname%TYPE--使用其他变量的属性声明DECLAREname VARCHAR(10) NOT NULL := 'ZhangSan';surname name%TYPE := 'LiSi';这样定义可以带来两个好处,首先,我们不用预先知道employee 表的firstname类型具体是什么。其次,即使之后firstname类型有了变化,我们也不需要再次修改my_name的类型。%ROWTYPE属性:%ROWTYPE属性主要用于对一组数据的类型声明,用于存储表中的一行数据,或从游标匹配的结果。假如,我们需要一组数据,该组数据的字段名称与字段类型都与employee表相同。我们可以通过如下定义:--根据表employee表结构定义变量类型DECLARE my_employee employee%ROWTYPE三、在GaussDB数据库中如何使用变量&常量(示例)变量&常量一般在数据库中不能直接应用到简单的SQL语句中,而是常常用于自定义的函数、存储过程中。下文简单举一列子(可参考前面FUNCTION/PROCEDURE相关文章):示例一,定义常量&变量(创建动态语句)常量作为WHERE 条件之一;变量存储查询的结果值。示例二,定义变量(创建游标)定义变量,存储游标结果值示例三,定义变量(创建package属性重载函数)定义TEXT类型变量、赋值SQL语句四、小结在GaussDB数据库中,变量和常量是两种不同的数据存储方式。变量是用于存储可变值的数据类型,可以在程序执行期间更改其值。而常量则是用于存储固定值的数据类型,其值在定义后不能被修改。 在GaussDB中,可以使用DECLARE语句来定义变量和常量,并通过使用“:=”运算符来为它们赋值。正确地定义和使用变量和常量可以提高程序的灵活性和可维护性,并确保数据的准确性和完整性。——结束
  • [技术干货] 大数据干货合集(2024年6月)
    融合分析能力是云原生数据仓库GaussDB(DWS)核心亮点之一。GaussDB(DWS)采用一套SQL引擎,支持Oracle、Mysql、HDFS等多源数据融合分析,并通过算子下推、加速集群等技术对分析性能进行了大幅优化,在数据免搬迁的前提下,实现了跨源数据免搬迁、高效分析。GaussDB(DWS)云原生数据仓库支持冷热数据多温存储,热数据存储于数仓内部,以获得良好的查询分析性能,冷数据可分级存储到更低成本的OBS中,不仅降低存储成本,并且在OBS内,通过合法鉴权,数据能够共享开放,供其他引擎处理分析,GaussDB(DWS)当前已经支持表内不同分区间的冷热数据存储,未来还将支持更细粒度、更加智能的冷热数据管理。GaussDB(DWS)性能优化最佳实践https://bbs.huaweicloud.com/forum/thread-0264154438478550040-1-1.html行存储和列存储的特点https://bbs.huaweicloud.com/forum/thread-0264154438609471041-1-1.html索引介绍https://bbs.huaweicloud.com/forum/thread-02127154438820523046-1-1.htmlGaussDB(DWS)性能调优Plan hint运用https://bbs.huaweicloud.com/forum/thread-0244154439166498047-1-1.html GaussDB(DWS)技术解读:融合分析能力https://bbs.huaweicloud.com/forum/thread-02109154439296560046-1-1.htmlGaussDB(DWS)技术解读:实时数仓https://bbs.huaweicloud.com/forum/thread-02127154439392517047-1-1.htmlGaussDB(DWS)技术特点https://bbs.huaweicloud.com/forum/thread-0224154439459494036-1-1.htmlGaussDB(DWS)的迁移工具https://bbs.huaweicloud.com/forum/thread-0210154439520486040-1-1.htmlCM组件介绍https://bbs.huaweicloud.com/forum/thread-0244154439658225048-1-1.htmlUnique SQL特性原理与应用https://bbs.huaweicloud.com/forum/thread-0273154439742484032-1-1.html用Unique SQL辅助定位问题https://bbs.huaweicloud.com/forum/thread-02109154439842964047-1-1.htmlGaussDB(DWS)delete误删数据后如何恢复https://bbs.huaweicloud.com/forum/thread-0244154440068495049-1-1.htmlvacuum full执行慢怎么办https://bbs.huaweicloud.com/forum/thread-0264154440311742042-1-1.htmlvacuum full的功能https://bbs.huaweicloud.com/forum/thread-0224154440495021037-1-1.htmlvacuum full执行慢的常见场景https://bbs.huaweicloud.com/forum/thread-0212154440623154031-1-1.html
  • [技术解读] GaussDB SQL基础语法示例-数组表达式
    一、前言SQL是用于访问和处理数据库的标准计算机语言。GaussDB支持SQL标准(默认支持SQL2、SQL3和SQL4的主要特性)。本系列将以《云数据库GaussDB—SQL参考》在线文档为主线进行介绍。欢迎使用GaussDB数据库数组表达式。在本文中,我们将介绍GaussDB数据库中数组表达式的概念、语法和用法。GaussDB是一种高性能、高可扩展的分布式数据库,广泛应用于各种业务场景。数组表达式是GaussDB数据库中的一种强大功能,它允许用户在数据库查询中使用数组操作符和函数来处理数组类型的数据。通过学习本文,您将了解如何使用GaussDB数据库的数组表达式来简化数据处理流程,提高查询效率,从而更好地满足业务需求。二、条件表达式的概念及GaussDB中的常见的数组表达式GaussDB支持SQL语言以及一些扩展功能。在GaussDB中,数组表达式用于处理数组类型的数据。以下是一些常见的数组表达式:1、IN :expression IN (value [, ...])使用IN运算符可以判断一个数组是否包含在一个给定的值列表中。如果数组包含所有在括号中指定的值,则返回true;否则返回false。2、NOT IN :expression NOT IN (value [, ...])使用NOT IN运算符可以判断一个数组是否不包含在一个给定的值列表中。如果数组不包含任何在括号中指定的值,则返回true;否则返回false。3、ANY(array):expression operator ANY (array expression)ANY运算符用于判断一个数组是否满足给定数组中的任何一个条件。其中,operator是比较运算符,如=、<、>等。如果左侧的数组满足右侧数组中的任何一个条件,则返回true;否则返回false。4、SOME (array) :expression operator SOME (array expression)SOME运算符用于判断一个数组是否满足给定数组中的至少一个条件。其中,operator是比较运算符,如=、<、>等。如果左侧的数组满足右侧数组中的至少一个条件,则返回true;否则返回false。 需要注意的是,SOME在GaussDB中的用法与ANY相同,因此上述例子同样适用于SOME。5、ALL (array) :expression operator ALL (array expression)ALL运算符用于判断一个数组是否满足给定数组中的所有条件。其中,operator是比较运算符,如=、<、>等。如果左侧的数组满足右侧数组中的所有条件,则返回true;否则返回false。三、GaussDB中常用的数组表达式(语法 + 示例)1、expression IN (value [, ...])右侧括号中的是一个数组表达式列表。左侧表达式的结果与表达式列表的内容进行比较。如果列表中的内容符合左侧表达式的结果,则IN的结果为true。如果没有相符的结果,则IN的结果为false。使用in的时候,忽略为null的,不会查询出为null的数据。如果表达式结果为null,或者表达式列表不符合表达式的条件且右侧表达式列表返回结果至少一处为空,则IN的返回结果为null,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。示例:基础表:教师表、课程表--在教师表中是否可以匹配到代课的老师SELECT * FROM course WHERE teid IN (SELECT teid FROM teacher );2、expression NOT IN (value [, ...])右侧括号中的是一个表达式列表。左侧表达式的结果与表达式列表的内容进行比较。如果在列表中的内容没有符合左侧表达式结果的内容,则NOT IN的结果为true。如果有符合的内容,则NOT IN的结果为false。如果查询语句返回结果为空,或者表达式列表不符合表达式的条件且右侧表达式列表返回结果至少一处为空,则NOT IN的返回结果为null,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。示例(基础表course、teacher见上文截图):--在教师表中是否可以匹配到代课的老师SELECT * FROM course WHERE teid NOT IN (SELECT teid FROM teacher );3、expression operator ANY/ SOME (array expression)右侧括号中的是一个数组表达式,它必须产生一个数组值。左侧表达式的结果使用操作符对数组表达式的每一行结果都进行计算和比较,比较结果必须是布尔值。如果对比结果至少获取一个真值,则ANY的结果为true。如果对比结果没有真值,则ANY的结果为false。如果结果没有真值,并且数组表达式生成至少一个值为null,则ANY的值为NULL,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。示例:基础表:部门1、部门2--查找部门1的员工年龄大于部门2的员工SELECT * FROM department1WHERE age > ANY (SELECT age FROM department2);SOME跟ANY 类似:--查找部门1的员工年龄大于部门2的员工SELECT * FROM department1WHERE age > SOME (SELECT age FROM department2);补充说明:> any 大于子查询结果中的某个值< any 小于子查询结果中的某个值>= any 大于或等于子查询结果中的某个值<= any 小于或等于子查询结果中的某个值= any 等于子查询结果中的某个值,相当于IN!= any 不等于子查询结果中的某个值4、expression operator ALL (array expression)右侧括号中的是一个数组表达式,它必须产生一个数组值。左侧表达式的结果使用操作符对数组表达式的每一行结果都进行计算和比较,比较结果必须是布尔值。如果所有的比较结果都为真值(包括数组不含任何元素的情况),则ALL的结果为true。如果存在一个或多个比较结果为假值,则ALL的结果为false。如果数组表达式产生一个NULL数组,则ALL的结果为NULL。如果左边表达式的值为NULL ,则ALL的结果通常也为NULL(某些不严格的比较操作符可能得到不同的结果)。另外,如果右边的数组表达式中包含null元素并且比较结果没有假值,则ALL的结果将是NULL(某些不严格的比较操作符可能得到不同的结果), 而不是真。这样的处理方式和SQL返回空值的布尔组合规则是一致的。示例:(基础表department1、department2见上文截图)SELECT * FROM department1WHERE age > ALL (SELECT age FROM department2);补充说明:> all 大于子查询结果中的所有值< all 小于子查询结果中的所有值>= all 大于或等于子查询结果中的所有值<= all 小于或等于子查询结果中的所有值= all 等于子查询结果中所有值!= all 不等于子查询结果中的任何一个值,相当于NOT IN四、小结通过本文的介绍,相信您已经对GaussDB数据库的数组表达式有了深入的了解。数组表达式是GaussDB数据库中非常实用的功能,它可以帮助您更高效地处理数组类型的数据,简化查询语句,提高查询效率。希望本文对您有所帮助。 ——结束
  • [技术解读] GaussDB SQL基础语法示例-常见的条件表达式
    一、前言SQL是用于访问和处理数据库的标准计算机语言。GaussDB支持SQL标准(默认支持SQL2、SQL3和SQL4的主要特性)。本系列将以《云数据库GaussDB—SQL参考》为主线进行介绍。二、条件表达式的概念及GaussDB中的常见条件表达式条件表达式是指在数据库中进行SQL语句查询时,根据特定条件筛选出符合要求的数据所使用的表达式。 在GaussDB数据库中,CASE、DECODE、COALESCE、NULLIF、GREATEST和NVL等都是常用的条件表达式。CASE:根据条件进行多分支判断,根据不同的条件返回不同的结果。DECODE:GaussDB数据库提供的函数功能,相当于SQL语言中的IF-THEN-ELSE语句,根据第一个参数和后续参数进行比较,返回符合条件的结果。COALESCE:返回第一个非空的参数值。如果所有参数都为空,那么就会返回NULL。COALESCE不会计算不需要用来判断结果的参数;即在第一个非空参数右边的参数不会被计算。NULLIF:用于比较两个字段的值,如果它们相等,则返回NULL,否则返回第一个字段的值。要求两个表达式数据类型一致。GREATEST:用于返回多个数字值中的最大值。NVL:接受两个参数,如果第一个参数为空,则返回第二个参数的值;如果第一个参数不为空,则返回第一个参数的值。下文将逐一进行介绍。三、GaussDB中常用的条件表达式(语法 + 示例)1、CASE表达式1)语法:CASE WHEN condition1 THEN result1WHEN condition2 THEN result2……ELSE resultEND说明:根据条件进行多分支判断,根据不同的条件返回不同的结果。如果结果为真,CASE表达式的结果就是符合该条件所对应的result。如果结果为假,则以相同方式处理随后的WHEN或ELSE子句。如果各WHEN condition都不为真,表达式的结果就是在ELSE子句执行的result。如果省略了ELSE子句且没有匹配的条件,结果为NULL。2)示例:SELECT name,age,CASEWHEN age < 18 THEN '未成年'WHEN age >= 18 AND age < 60 THEN '成年'ELSE '老年'END AS age_groupFROM company;解析:这段代码主要是从 "company" 表中选择 "name" 和 "age" 数据,并通过“CASE表达式”为每个用户生成一个根据年龄划分的组别('未成年'、'成年' 或 '老年')。另参见,前面的文章《GaussDB SQL基本语法示例-CASE表达式》 。2、DECODE表达式1)语法:DECODE(base_expression,compare1,value1,compare(n),value(n),default)说明:GaussDB数据库提供的函数功能,相当于IF-THEN-ELSE语句,根据第一个参数和后续参数进行比较,返回符合条件的结果。2)示例:SELECT name,salary,DECODE(salary, NULL, '未知', 5000, '初级标准线', 20000, '中级标准线',30000, '高级级标准线', '其他') AS salary_levelFROM company ORDER BY salary ;解析:这段代码的目的是从 "company" 表中选择 "name" 和 "salary" 数据,并通过“DECODE表达式”定义工资级别('未知'、'初级标准线'、'中级标准线'、 '高级标准线'、‘其他’)。3、COALESCE表达式1)语法:COALESCE(value1,value2,…)说明:返回第一个非空的参数值。如果所有参数都为空,那么就会返回NULL。COALESCE不会计算不需要用来判断结果的参数;即在第一个非空参数右边的参数不会被计算。2)示例:SELECT name,COALESCE(address, '未知地址') AS addressFROM company;解析:这个查询将返回每个员工的名字和地址,通过“表达式COALESCE”判断,如果地址未知,它将显示 '未知地址'。4、NULLIF表达式1)语法:NULLIF(value1,value2)说明:用于比较两个字段的值,如果它们相等,则返回NULL,否则返回第一个字段的值。要求两个表达式数据类型一致。2)示例:SELECT NULLIF('abc', 'abc'); -- 返回NULLSELECT NULLIF('abc', '123'); -- 返回'123'5、GREATEST/ LEAST表达式1)语法:GREATEST(value1,value2,…)LEAST(value1,value2,…)说明:GREATEST用于返回多个数字值中的最大值。LEAST,从一个任意数字表达式的列表里选取最小的数值。以上的数字表达式必须都可以转换成一个普通的数据类型。2)示例:SELECT GREATEST(10, 20, 30); -- 返回30SELECT LEAST(10, 20, 30); -- 返回106、NVL表达式1)语法:NVL(value1,value2,…)说明:接受两个参数,如果第一个参数为空,则返回第二个参数的值;如果第一个参数不为空,则返回第一个参数的值,参数类型必须一致。2)示例:SELECT name,salary,NVL(salary,default_salary) AS d_salaryFROM company;解析:这个查询将返回每个员工的名字和薪水,通过“表达式NVL”判断,如果salary为空,则用取默认的default_salary 。四、小结条件表达式是数据库查询中非常有用的工具,今天介绍的CASE、DECODE、COALESCE、NULLIF、GREATEST和NVL等,在GaussDB数据库中是非常常用的,通过使用这些条件表达式,我们可以更加灵活地对数据进行查询和操作,提高程序的效率和可读性。同时,它们也使得数据的处理更为方便和快捷,为数据分析和决策提供了有力的支持。--结束
  • [技术解读] GaussDB关键技术原理:高性能(二)
     GaussDB关键技术原理:高性能(一)从数据库性能优化系统概述对GaussDB的高性能技术进行了解读,本篇将从查询处理综述方面继续分享GaussDB的高性能技术的精彩内容。2 查询处理综述内容概要:本章节介绍查询端到端处理的执行流程,首先让读者对查询在数据库内部如何执行有一个初步的认识,充分理解查询处理各阶段主要瓶颈点以及对应的解决方案,本章以GaussDB为例讲解查询执行的几个主要阶段,并且对相关的模块的重要优化点优化方向予以明确。目的:通过对数据库执行处理过程的理解,能够把数据库性能调优分析的理解更加白盒化,在后续了解优化手段的同时也能够对根本内部实现原理有一个理解,能够让读者更加深入理解数据优化的核心理论实现。2.1 查询处理流程查询在经典数据库实现中需要依次进行以下4个环节,(1)查询解析:对用户输入查询进行编译,把查询从文本方式翻译成执行引擎可以识别的语句。(2)查询优化:对查询的进行基于规则的逻辑优化RBO和基于代价CBO的物理优化(3)查询执行:将查询执行计划高效执行(4)数据读取:实现对数据库的高效读取(5)分布式执行:实现数据库的高效通信(分布式数据库)​对数据库的执行过程来说以上每个环节处理所花销的时间都是对最后查询执行时间的组成,因此每个环节执行效率都对性能会产生影响,决定查询端到端的性能。2.2 查询解析器查询解析是指将用户的SQL文本输入转换为数据库内核能够进行逻辑运算的翻译过程,SQL的解析过程主要分为以下几个阶段:​(1)词法分析Lexical Analysis:将用户输入的SQL语句拆解成单词(Token)序列,并识别出关键字、标识、常量等(2)语法分析Syntax Analysis:分析器对词法分析器解析出来的单词(Token)序列在语法上是否满足SQL语法规则,通常识别出语法错误问题(3)语义分析Semantic Analysis:语义分析是SQL解析过程的一个逻辑阶段,主要任务是在语法正确的基础上进行上下文有关性质的审查,在SQL解析过程中该阶段完成表名、操作符、类型等元素的合法性判断,同时检测语义上的二义性问题以下是例举查询解析的全过程,从用户输入的SQL语句开始,依次经历了词法、语法、语义解析几个阶段:​查询解析阶段影响性能的关键因素:(1)词法、语法分析效率(2)语义分析效率(3)查询的复杂度查询解析阶段优化技术:查询缓存技术,模板查询免解析2.3 查询优化器查询优化阶段主要是SQL执行过程中在优化器SQL Optimizer中执行的部分,优化器作为数据库的大脑是SQL执行路径决策者,从全局视角出发提升查询的性能,降低用户使用数据库调优的门槛。查询优化总体上分为逻辑优化、物理优化。​查询优化从总体上可以分成两类:1、基于规则的逻辑优化(Rule-Base-Optimization),根据等价逻辑的变换让查询的计算复杂度降低,从而达到提升查询性能的作用。​上述例子中,通过等价outer join -> inner join变换,可以避免对内表结果集NULL的处理,减少了处理数据量,进而提升性能。2、基于代价的物理优化(Cost-Base-Optimization),根据数据的分布(统计信息)情况来对查询执行路径进行评估,从可选的路径中选择一个执行代价最小的路径进行执行,例如是否选择索引SeqScan vs. IndexScan、选择哪个索引,两表关联选择什么样的连接顺序,选择怎样的具体算法等。​上述例子中,对数据量的准确评估,确定表关联的顺序,进而提升性能。查询优化阶段的核心点:高效生成执行计划,有效消减处理数据的数据量、缩短执行流程,提升查询性能。查询优化阶段优化技术:查询重写、基于成本预估的路径生成。2.4 查询执行器执行引擎负责查询的执行,在SQL执行栈中起到接受优化器生成的执行计划Plan、并对通过存储引擎提供的数据读写接口,实现对数据进行计算得到查询的结果集。在分布式数据库中,执行引擎的范围还应包括节点间网络数据交换和传输的部分。经典的执行模型:Tuple-At-A-Time模型(Volcano-Model)数据库的执行是把查询的处理步骤抽象成独立的基础算子,然后由执行框架驱动算子迭代的方式执行,每个算子抽象成open()/next()/close()三种操作,上层算子通过嵌套调用下层的next()进行处理数据的返回,同样初始化的过程和结束过程也通过open()/close()嵌套调用,火山模型也是大多数传统数据库实现的执行模型。计划节点typedef struct Operator{ NodeTag ... /* input plan tree(s) */ struct Operator *lefttree; struct Operator *righttree; ...} Plan;计划节点迭代执行/* operator open 初始化操作 */State *exec_init_opr(state){ switch(nodeTag(state)) { ... }}/* operator next 执行操作 */Tuple *exec_process(plan){ switch(nodeTag(plan)) { case Scan: exec_scan(); case Join: exec_join(); // process state->left & righttree{ exec_proc_node(state->lefttree); exec_proc_node(state->righttree);} case Agg: exec_agg(); ... }}/* operator close 结束操作 */void exec_deinit (state){ switch(nodeTag(state)) { ... }}关系数据库本身是对关系集合Relation的运算操作,执行引擎作为运算的控制逻辑主题夜视仪围绕着关系运算来实现的,在传统数据库实现理论中,算子的分类可以分成以下几类:1、扫描类算子(Scan Plan Node)扫描节点负责从底层数据来源抽取数据,数据来源可能是来自文件系统,也可能来自网络(分布式查询)。一般而言扫描节点都位于执行树的叶子节点,作为执行数的数据输入来源,典型代表SeqScan、IndexScan、SubQueryScan关键特征:输入数据、叶子节点、表达式过滤2、控制类算子(Control Plan Node)控制算子一般不映射代数运算符,是为了执行器完成一些特殊的流程引入的算子,例如Limit、RecursiveUnion、Union关键特征:用于控制数据流程3、物化算子(Materialize Plan Node)物化算子一般指算法要求,在做算子逻辑处理的时候,要求把下层的数据进行缓存处理,因为对于下层算子返回的数据量不可提前预知,因此需要在算法上考虑数据无法全部放置到内存的情况,例如Agg、Sort关键特征:需要扫描所有数据之后才返回4、连接算子(Join Plan Node)这类算子是为了应对数据库中最常见的关联操作,根据处理算法和数据输入源的不同分成以下几种关键特征:多个输入传统执行模型的优缺点优点:逻辑清晰,可读性可维护性较好缺点:由于存在大量的function call, instruction cache missing因此运行效率低2.5 分布式执行分布式执行主要为分布式数据库提供一套完备的支撑数据跨节点交换,协同计算的计算框架,能够支撑位于不同地点的许多计算分片机通过网络互相连接,共同组成一个完整的、全局的逻辑上集中、物理上分布的大型数据库,数据的分布式切片方式从大的分类上有3种:(1)Share-Memory共享内存(典型代表SQL Server),多个处理进程共享同一片内存,处理进程之间通过内部通讯机制进行通讯,通常具有很高的效率;但当更多的处理进程被添加到主机上时,内存/CPU资源竞争就成为瓶颈,进程越多瓶颈越厉害(2)Share-Disk共享磁盘(典型代表Oracle RAC),各个处理单元使用自己的私有 CPU和Memory,共享磁盘系统,可通过增加节点来提高并行处理的能力,扩展能力较好,类似于SMP(对称多处理)模式,这种架构需要通过一个狭窄的数据管道将所有I/O信息过滤到昂贵的共享磁盘子系统,当存储器接口达到饱和的时候,增加节点并不能获得更高的性能 。(3)Share-Nothing无共享(典型代表Teradata,GaussDB),各个处理单元都有自己私有的CPU/内存/硬盘等彼此之间相互独立,类似于MPP(大规模并行处理)模式,它是把某个表从物理存储上被水平分割,并分配给多台服务器(或多个实例),每台服务器可以独立工作,各处理单元之间通过协议通信,并行处理和扩展能力更好,只需增加服务器数就可以增加处理能力和容量,缺点是对于数据分库分表的设计存在门槛。分布式执行-数据的分布与分区:GaussDB的分布式部署模式采用shared-nothing方式,每个定义的表逻辑上通过分布列进行分布,通过分布类查询可以做到单DN访问。分布式执行:数据重分布Data-Shuffling分布式数据库中当两表关联的时候,如果有一张表的关联键不是分布键,或者发生聚集操作GroupKey不是分布键,那么就会发生表的广播或者重分布,将数据移动到一个节点上进行关联,否则查询的正确性无法得到保证。数据库工作节点数据迁移的类型主要有Broadcast广播(N:1)和Redistribute重分布(N:M)两种表信息: - T1: distribute By HASH(c1) - T2: distribute By HASH(c2)执行查询: - select * from t1 join t2 on t1.c1 = t2.c1由于T1、T2的分布键不相同,直接在各个datanode上关联T1、T2查询的结果正确性无法保证。方案1:对表T2按照t2.c1的键值进行重分布redistribute操作redis(t2)->t2’, t1 join t2’方案2:对T1进行复制broadcast操作dup(t1)->t1’, t1’join t2方案3:对T2进行复制broadcast操作dup(t2)->t2’, t2’join t1对于两表关联中如果之间的Data-Locality不匹配,则需要先进行data-shuffling方可进行关联操作,data-shuffling的方案根据代价通常是数据移动的成本(数据量大小、数据倾斜)因素由优化器进行判断。2.6 存储引擎数据读取存储引擎主要实现高效存储数据确保数据库ACID(原子性、一致性、隔离性、持久性),正确并发读写、高性能读写等问题,从查询处理的视角通常执行算子Scan层调用存储引擎的数据读取接口进行数据读写,传统的存储引擎在查询处理的位置如下图GaussDB包含多种存储模式,按照存储格式划分可分为行存储格式、列存储格式,其中前者,主要适合在线交易类型业务(OLTP)而后者主要适合数据分析类型业务 (OLAP),此外还包含PAX混合存储格式,目前商用数据库支持的不多,开源的如ORC, Parquet格式,主要也是用于OLAP场景。存储引擎主要核心模块:(1)数据页面缓存池:数据页面读写先从页面缓存里读取和修改,如果缓存里不存在,再从数据文件读取页面。(2)堆表Heap:表数据存储格式和访问接口(3)索引Index:高效查询表数据(4)日志WAL:  修改数据页面,必须先写WAL日志(redo log),  事务提交之前和脏页写盘之前必须保证WAL日志持久化到存储设备。(5)事务并发控制: 正确读写,高性能并发读写。(6)事务提交日志: 事务状态和提交时间戳(7)WAL日志恢复:从检查点日志往后回放WAL日志索引技术索引在数据库中的实现为B树结构,索引的键值按照B树进行排序,能够将索引键值的查找由线性查找优化成B树查找。(1)对于非叶子节点,indexTup指向下一个节点,而对于叶子节点,indexTup指向堆表里的行(2)Special space中,实现了两个指针,用于指向左右兄弟节点。(3)索引元组有序,第一个叶子节点中indexTup3实际为最大健值索引元组,即high key,第二个叶子节点中IndexTup1跟indexTup3指向相同的堆表中的行。High key是为了减少比较次数。数据页面缓冲区数据页面缓冲池设计主要是为了减少磁盘的读写。读页面尽可能多的命中内存buffer page,减少磁盘读取页面, 写操作批量刷盘,  而不是每修改一条数据,就写数据页面。(1)为了提高缓存命中率,设计缓存淘汰算法来保证频繁访问的热页面尽量在内存buffer里(2)设计多个buffer pool用于缓存不同的对象,一方面为了减少冲突,同时也提高了缓存命中率(3)对于批量导入和批量读取的场景, 为避免污染整个buffer pool,  顺序读取一遍表数据,把整个buffer pool里页面都淘汰。设计buffer 批量读写获取策略,采用buffer ring的策略,固定范围的获取free buffer。以上内容为查询处理综述的相关内容,下篇将分享高性能关键技术的精彩内容,敬请期待!
  • [问题求助] GaussDB随着表中的数据越来越多,是否也要做手动分库分表?不分的话是否会影响性能
    GaussDB随着表中的数据越来越多,是否也要做手动分库分表?不分的话是否会影响性能
  • [问题求助] GaussDB单表最多能存储多少数据
    GaussDB单表最多能存储多少数据
  • [问题求助] 视图的DDL有什么方法能恢复原样
    创建了一个视图后,在data studio里面查看这个视图的DDL,代码如下CREATE OR REPLACE VIEW riskdata.XXXX AS SELECT a.news_id, a.news_source_id, a.title AS news_title, a.url AS news_link, b.news_source, COALESCE(b.news_text_nohtml, b.news_text) AS news_text, b.publish_time, a.publish_type, a.ori_publish_type, a.publish_institution, a.ori_pub_inst, f_news_penalty_zj_pubinst_XXX(a.ori_pub_inst) AS area, f_news_penalty_zj_pubinst_XXX(a.publish_institution, a.ori_pub_inst) AS org_type FROM (t_news_penalty a LEFT JOIN t_news_info b ON (((a.news_id)::text = (b.news_id)::text))) WHERE ((EXISTS (SELECT 1 AS "?column?" FROM t_news_penalty_object b WHERE (((a.news_id)::text = (b.news_id)::text) AND ((b.object_type)::text = ANY ((ARRAY['02'::character varying, '03'::character varying])::text[]))))) AND ((a.data_source)::text = 'NLPPLATFORM.PENALTY'::text));主要的问题是注释没有了;可读性很差,非常不好维护