华为云用户手册

  • DELETE 不支持DELETE语句中使用LIMIT。应使用WHERE条件明确需要更新的目标行。 在GMT-FREE模式下,不允许跨节点事务,因此删除HASH分布表中数据时,必须在WHERE条件中指定分布列等值过滤条件。 不支持多表删除。 多表删除即在单条SQL语句中,对多个表进行删除。 DELETE语句中必须有WHERE子句,避免全表扫描。 DELETE语句中禁止不应使用ORDER BY、GROUP BY子句,避免不必要的排序。 如果需要清空一张表,建议使用TRUNCATE,而不是DELETE。 TRUNCATE会创建新的物理文件,并在事务结束时将原文件物理删除,清空磁盘空间。而DELETE会将表中数据进行标记,直到VACUUM FULL阶段才会真正清理磁盘空间。 DELETE有主键或索引的表,WHERE条件应结合主键或索引,提高执行效率。 父主题: 数据库编程规范
  • 参数说明 join_table_list为表示表join顺序的hint字符串,可以包含当前层的任意个表(别名),或对于子查询提升的场景,也可以包含子查询的hint别名,同时任意表可以使用括号指定优先级,表之间使用空格分隔。 表只能用单个字符串表示,不能带schema。 表如果存在别名,需要优先使用别名来表示该表。 join table list中指定的表需要满足以下要求,否则会报语义错误。 list中的表必须在当前层或提升的子查询中存在。 list中的表在当前层或提升的子查询中必须是唯一的。如果不唯一,需要使用不同的别名进行区分。 同一个表只能在list里出现一次。 如果表存在别名,则list中的表需要使用别名。 例如: leading(t1 t2 t3 t4 t5)表示:t1, t2, t3, t4, t5先join,五表join顺序及内外表不限。 leading((t1 t2 t3 t4 t5))表示:t1和t2先join,t2做内表;再和t3 join,t3做内表;再和t4 join,t4做内表;再和t5 join,t5做内表。 leading(t1 (t2 t3 t4) t5)表示:t2, t3, t4先join,内外表不限;再和t1, t5 join,内外表不限。 leading((t1 (t2 t3 t4) t5))表示:t2, t3, t4先join,内外表不限;在最外层,t1再和t2, t3, t4的join表join,t1为外表,再和t5 join,t5为内表。 leading((t1 (t2 t3) t4 t5)) leading((t3 t2))表示:t2,t3先做join,t2做内表;然后再和t1做join,t2,t3的join表做内表;然后再跟t4做join,t4做内表,最后和t5做join,t5做内表。
  • 示例 对示例中原语句使用如下hint: explain select /*+ leading((((((store_sales store) promotion) item) customer) ad2) store_returns) leading((store store_sales))*/ i_product_name product_name ... 该hint表示:表之间的join关系是:store_sales和store先join, store_sales做内表,然后依次跟promotion, item, customer, ad2, store_returns做join。生成计划如下所示: 图中计划顶端warning的提示详见Hint的错误、冲突及告警的说明。
  • 选择存储模型 进行数据库设计时,表设计上的一些关键项将严重影响后续整库的查询性能。表设计对数据存储也有影响:好的表设计能够减少I/O操作及最小化内存使用,进而提升查询性能。 表的存储模型选择是表定义的第一步。客户业务属性是表的存储模型的决定性因素,依据下面表格选择适合当前业务的存储模型。 存储模型 适用场景 行存 点查询(返回记录少,基于索引的简单查询)。 增删改比较多的场景。 列存 统计分析类查询 (group , join多的场景)。 父主题: 审视和修改表定义
  • 支持审计的关键操作列表 通过 云审计 服务,您可以记录与 GaussDB 实例相关的操作事件,便于日后的查询、审计和回溯。 表1 云审计服务支持的操作列表 操作名称 资源类型 事件名称 创建实例、恢复到新实例 instance createInstance 删除实例 instance deleteInstance 数据库实例规格变更 instance resizeFlavor 实例版本升级 instance upgradeVersion 密码重置 instance resetPassword 实例重启 instance instanceRestart 绑定公共IP instance setOrResetPublicIP 解绑公共IP instance setOrResetPublicIP 修改资源标签 instance modifyTag 删除资源标签 instance deleteTag 添加资源标签 instance createTag 重命名实例 instance instanceRename 实例扩容 instance instanceAction 删除任务记录 instance deleteTaskRecord4OpenGauss 减少副本 instance reduceReplica 协调节点缩容 instance reduceCoordinatorNode 设置回收站策略 backup setRecyclePolicy 创建手动备份 backup createManualSnapshot 删除手动备份 backup deleteManualSnapshot 修改备份策略 backup setBackupPolicy 实例还原 backup restoreInstance 备份恢复实例 instance restoreInstance 修改/更新自动备份保留时长 instance setBackupPolicy 创建参数组 parameterGroup createParameterGroup 应用参数组 parameterGroup applyParameterGroup 复制参数组 parameterGroup copyParameterGroup 删除参数组 parameterGroup deleteParameterGroup 重置参数组 parameterGroup resetParameterGroup 更新参数组 parameterGroup updateParameterGroup 修改端口号 instance modifyPort 父主题: CTS 审计
  • 不支持下推的函数 首先介绍函数的易变性。在GaussDB中共分三种形态: IMMUTABLE 表示该函数在给出同样的参数值时总是返回同样的结果。 STABLE 表示该函数不能修改数据库,对相同参数值,在同一次表扫描里,该函数的返回值不变,但是返回值可能在不同SQL语句之间变化。 VOLATILE 表示该函数值可以在一次表扫描内改变,因此不会做任何优化。 函数易变性可以查询pg_proc的provolatile字段获得,i代表IMMUTABLE,s代表STABLE,v代表VOLATILE。另外,在pg_proc中的proshippable字段,取值范围为t/f/NULL,这个字段与provolatile字段一起用于描述函数是否下推。 如果函数的provolatile属性为i,则无论proshippable的值是否为t,则函数始终可以下推。 如果函数的provolatile属性为s或v,则仅当proshippable的值为t时,函数可以下推。 random,exec_hadoop_sql,exec_on_extension如果出现CTE中,也不下推。因为这种场景下下推可能出现结果错误。 对于用户自定义函数,可以在创建函数的时候指定provolatile和proshippable属性的值,详细请参考CREATE FUNCTION语法。 对于函数不能下推的场景: 如果是系统函数,建议根据业务等价替换这个函数。 如果是自定义函数,建议分析客户业务场景,看函数的provolatile和proshippable属性定义是否正确。
  • 语句下推介绍 目前,GaussDB优化器在分布式框架下制定语句的执行策略时,有三种执行计划方式:生成下推语句计划、生成分布式执行计划、生成发送语句的分布式执行计划。 下推语句计划:指直接将查询语句从CN发送到DN进行执行,然后将执行结果返回给CN。 分布式执行计划:指CN对查询语句进行编译和优化,生成计划树,再将计划树发送给DN进行执行,并在执行完毕后返回结果到CN。 发送语句的分布式执行计划:上述两种方式都不可行时,将可下推的查询部分组成查询语句(多为基表扫描语句)下推到DN进行执行,获取中间结果到CN,然后在CN执行剩下的部分。 在第3种策略中,要将大量中间结果从DN发送到CN,并且要在CN运行不能下推的部分语句,会导致CN成为性能瓶颈(带宽、存储、计算等)。在进行性能调优的时候,应尽量避免只能选择第3种策略的查询语句。 执行语句不能下推是因为语句中含有不支持下推的函数或者不支持下推的语法。一般都可以通过等价改写规避执行计划不能下推的问题。
  • UPDATE 不支持UPDATE语句中直接使用LIMIT,应使用WHERE条件明确需要更新的目标行。 在GTM-FREE模式下,不允许跨节点事务,因此更新HASH分布中数据表时WHERE条件中必须指定分布列等值过滤条件。 不支持多表更新。 多表更新即在单条SQL语句中,对多个表进行更新。 UPDATE语句中必须有WHERE子句,避免全表扫描。 不允许在UPDATE子句同时更新多个列时,被更新列同样是更新源。 同时更新多列,且更新源相同,在不同的数据库下行为不同,为了避免带来兼容性问题,业务层应避免上述操作。 示例: UPDATE table SET col1 = col2, col3 = col1 WHERE col1 = 1; 该语句在GaussDB中,col3的值为原col1的值;而MySQL中,col3的值为col2的值(因为col2的值被赋予给了col1)。 UPDATE语句中禁止使用ORDER BY、GROUP BY子句,避免不必要的排序。 有主键/索引的表,更新时WHERE条件应结合主键/索引。 父主题: 数据库编程规范
  • 示例 为了hint使用索引扫描,需要首先在表item的i_item_sk列上创建索引,名称为i。 create index i on item(i_item_sk); 对示例中原语句使用如下hint: explain select /*+ indexscan(item i) */ i_product_name product_name ... 该hint表示:item表使用索引i进行扫描。生成计划如下所示:
  • 参数说明 no表示hint的scan方式不使用。 table表示hint指定的表,只能指定一个表,如果表存在别名应优先使用别名进行hint。 index表示使用indexscan或indexonlyscan的hint时,指定的索引名称,当前只能指定一个。 对于indexscan或indexonlyscan,只有hint的索引属于hint的表时,才能使用该hint。 scan hint支持在行列存表、obs表、子查询表上指定。
  • Hint的错误、冲突及告警 Plan Hint的结果会体现在计划的变化上,可以通过explain来查看变化。 Hint中的错误不会影响语句的执行,只是不能生效,该错误会根据语句类型以不同方式提示用户。对于explain语句,hint的错误会以warning形式显示在界面上,对于非explain语句,会以debug1级别日志显示在日志中,关键字为PLANHINT。 hint的错误分为以下类型: 语法错误 语法规则树归约失败,会报错,指出出错的位置。 例如:hint关键字错误,leading hint或join hint指定2个表以下,其它hint未指定表等。一旦发现语法错误,则立即终止hint的解析,所以此时只有错误前面的解析完的hint有效。 例如: leading((t1 t2)) nestloop(t1) rows(t1 t2 #10) nestloop(t1)存在语法错误,则终止解析,可用hint只有之前解析的leading((t1 t2))。 语义错误 表不存在,存在多个,或在leading或join中出现多次,均会报语义错误。 scanhint中的index不存在,会报语义错误。 另外,如果子查询提升后,同一层出现多个名称相同的表,且其中某个表需要被hint,hint会存在歧义,无法使用,需要为相同表增加别名规避。 hint重复或冲突 如果存在hint重复或冲突,只有第一个hint生效,其它hint均会失效,会给出提示。 hint重复是指,hint的方法及表名均相同。例如:nestloop(t1 t2) nestloop(t1 t2)。 hint冲突是指,table list一样的hint,存在不一样的hint,hint的冲突仅对于每一类hint方法检测冲突。 例如:nestloop (t1 t2) hashjoin (t1 t2),则后面与前面冲突,此时hashjoin的hint失效。注意:nestloop(t1 t2)和no mergejoin(t1 t2)不冲突。 leading hint中的多个表会进行拆解。例如:leading ((t1 t2 t3))会拆解成:leading((t1 t2)) leading(((t1 t2) t3)),此时如果存在leading((t2 t1)),则两者冲突,后面的会被丢弃。(例外:指定内外表的hint若与不指定内外表的hint重复,则始终丢弃不指定内外表的hint。) 子链接提升后hint失效 子链接提升后的hint失效,会给出提示。通常出现在子链接中存在多个表连接的场景。提升后,子链接中的多个表不再作为一个整体出现在join中。 列类型不支持重分布 对于skew hint来说,目的是为了进行重分布时的调优,所以当hint列的类型不支持重分布时,hint将无效。 hint未被使用 非等值join使用hashjoin hint或mergejoin hint。 不包含索引的表使用indexscan hint或indexonlyscan hint。 通常只有在索引列上使用过滤条件才会生成相应的索引路径,全表扫描将不会使用索引,因此使用indexscan hint或indexonlyscan hint将不会使用。 indexonlyscan只有输出列仅包含索引列才会使用,否则指定时hint不会被使用。 多个表存在等值连接时,仅尝试有等值连接条件的表的连接,此时没有关联条件的表之间的路径将不会生成,所以指定相应的leading,join,rows hint将不使用,例如:t1 t2 t3表join,t1和t2, t2和t3有等值连接条件,则t1和t3不会优先连接,leading(t1 t3)不会被使用。 生成stream计划时,如果表的分布列与join列相同,则不会生成redistribute的计划;如果不同,且另一表分布列与join列相同,只能生成redistribute的计划,不会生成broadcast的计划,指定相应的hint则不会被使用。 如果子链接未被提升,则blockname hint不会被使用。 对于skew hint,hint未被使用可能由于: 计划中不需要进行重分布。 hint指定的列为包含分布键。 hint指定倾斜信息有误或不完整,如对于join优化未指定值。 倾斜优化的GUC参数处于关闭状态。 父主题: 使用Plan Hint进行调优
  • 选择分布列 Hash分布表的分布列选取至关重要,需要满足以下原则: 列值应比较离散,以便数据能够均匀分布到各个DN。例如,考虑选择表的主键为分布列,如在人员信息表中选择身份证号码为分布列。 在满足第一条原则的情况下尽量不要选取存在常量filter的列。例如,表t1相关的部分查询中出现t1的列zqdh存在常量的约束(例如zqdh=’000001’),那么就应当尽量不用zqdh做分布列。 在满足前两条原则的情况,考虑选择查询中的连接条件为分布列,以便Join任务能够下推到DN中执行,且减少DN之间的通信数据量。 对于Hash分表策略,如果分布列选择不当,可能导致数据倾斜,查询时出现部分DN的I/O短板,从而影响整体查询性能。因此在采用Hash分表策略之后需对表的数据进行数据倾斜性检查,以确保数据在各个DN上是均匀分布的。可以使用以下SQL检查数据倾斜性 select xc_node_id, count(1) from tablename group by xc_node_id order by xc_node_id desc; 其中xc_node_id对应DN,一般来说,不同DN的数据量相差5%以上即可视为倾斜,如果相差10%以上就必须要调整分布列。 GaussDB支持多分布列特性,可以更好地满足数据分布的均匀性要求。 父主题: 审视和修改表定义
  • 优化分析 上述两个特征表明了此SQL语句存在极为严重的计算倾斜。进一步向HashJoin算子的下层分析发现Seq Scan on s_riskrate_setting也存在极为严重的计算倾斜[38.885,2940.983]。根据Scan的含义推测此计划性能问题的根源在于表s_riskrate_setting数据的分布倾斜。实际分析之后确实发现表s_riskrate_setting存在严重的数据倾斜。整改之后性能从94s提升为50s。
  • 现象描述 某局点测试过程中EXPLAIN ANALYZE后有如下情况: 从执行信息上比较明确的可以看出HashJoin是整个计划的性能瓶颈点,并且从HashJoin的执行时间信息[2657.406,93339.924](数值的具体含义请参见SQL执行计划详解),上可以看出HashJoin在不同的DN上存在严重的计算偏斜。 同时在Memory Information(如下图)中可以看出各个节点的内存资源消耗也存在极为严重的偏斜。
  • 表设计规范 必须指定表分布(DISTRIBUTE BY),表分布策略选择的原则如下: 目前提供REPLICATION和HASH两种表分布策略。REPLICATION分布会在每个节点保留一份相同的完整的数据表。HASH分布会根据所提供的分布键值将表数据分布到多个节点中。 对于系统配置表、数据字典表等数据规模小于2000w且插入更新十分低频的表,建议采用REPLICATION分布。 慎用REPLICATION分布,该分布表会造成空间膨胀、DML性能下降等负面影响。 对于数据量较大,更新频率较高的表,必须进行数据分片,要求采用HASH分布策略,分布键建议是主键中的一个或多个字段。 合理设计分布键,既要考虑查询开发的便利性,又要考虑数据的均匀存储,避免数据倾斜和读热点。 Hash表的分布键选取至关重要,如果分布键选择不当,可能会导致数据倾斜,从而导致查询时,I/O负载集中在部分DN上,影响整体查询性能。因此,在确定Hash表的分布策略之后,需要对表数据进行倾斜性检查,以确保数据的均匀分布。 应使用取值较为离散的字段作为分布键,以便数据能够均匀分布到各个DN中。 在满足条件1情况下,存在常量过滤的字段不建议成为分布键,否则会使得所有的查询任务都会分发到唯一固定的DN上。 在满足条件1和2原则下,尽量选择查询中的关联条件作为分布键,这样可保证JOIN任务的相关数据分布在相同的DN上,减少DN间数据的流动代价。 尽量避免数据shuffle。shuffle,是指在物理上,数据从一个节点,传输到另一个节点。shuffle占用了大量宝贵的网络资源,减小不必要的数据shuffle,可以减少网络压力,使数据的处理本地化,提高集群的性能和可支持的并发度。通过对关联条件和分组条件的仔细设计,能够尽可能的减少不必要的数据shuffle。 由于数据库规格要求HASH分布表的主键必须包含其分布列,因此在选择分布列时,也可以考虑选择表的主键作为分布键。 表1 常见的分布键及效果 分布键值 分布键分布均匀性 用户 ID,应用程序中有许多用户。 好 状态代码,只有几个可用的状态代码。 差 项目创建日期,四舍五入至最近的时间段(例如,天、小时或分钟)。 差 设备 ID,每个设备以相对类似的间隔访问数据. 好 分布键使用的列长度不易超过128,过长会带来较高的计算开销。 分布键值一旦插入不允许更新(UPDATE),如需更新需删除后插入。 视图不允许嵌套。 一方面,如果视图编写时使用了通配符,当被调用的视图新增或删除列时,视图将发生错误。 另一方面,视图嵌套可能因无法使用索引而执行效率低下,尽量使用带有索引的基表而不是视图上做关联操作。 分布键不建议超过3列,列数过多将带来较高的计算开销。 视图定义中尽量避免排序操作。 ORDER BY子句在顶层视图上无效,如果必须对输出数据排序,请考虑在调用视图中使用ORDER BY。 父主题: 数据库设计规范
  • 算子级调优介绍 一个查询语句要经过多个算子步骤才会输出最终的结果。由于各别算子耗时过长导致整体查询性能下降的情况比较常见。这些算子是整个查询的瓶颈算子。通用的优化手段是EXPLAIN ANALYZE/PERFORMANCE命令查看执行过程的瓶颈算子,然后进行针对性优化。 如下面的执行过程信息中,Hashagg算子的执行时间占总时间的:(51016-13535)/ 56476 ≈66%,此处Hashagg算子就是这个查询的瓶颈算子,在进行性能优化时应当优先考虑此算子的优化。
  • 子查询 禁止一条SQL语句中,出现重复子查询语句。 少用标量子查询。 标量子查询指结果为1个值,并且条件表达式为等值的子查询。 示例:不符合规范的语句 SELECT * FROM t1 WHERE id = (SELECT id FROM t2 LIMIT 1); 上述语句建议业务拆分为两条SQL语句,先执行子查询。 避免在SELECT目标列中使用子查询,可能导致计划无法下推影响执行性能。 子查询嵌套深度建议不超过2层。 由于子查询会带来临时表开销,过于复杂的查询应考虑从业务逻辑上进行优化。 父主题: 数据库编程规范
  • 操作步骤 使用DAS或者gsql连接实例。 查看阻塞的查询语句及阻塞查询的表、模式信息。 SELECT w.query as waiting_query, w.pid as w_pid, w.usename as w_user, l.query as locking_query, l.pid as l_pid, l.usename as l_user, t.schemaname || '.' || t.relname as tablename from pg_stat_activity w join pg_locks l1 on w.pid = l1.pid and not l1.granted join pg_locks l2 on l1.relation = l2.relation and l2.granted join pg_stat_activity l on l2.pid = l.pid join pg_stat_user_tables t on l1.relation = t.relid where w.waiting; 该查询返回线程ID、用户信息、查询状态,以及导致阻塞的表、模式信息。 使用如下命令结束相应的会话。 SELECT PG_TERMINATE_BACKEND(139834762094352); 其中,139834762094352为线程ID。 显示类似如下信息,表示结束会话成功。 PG_TERMINATE_BACKEND ---------------------- t (1 row) 显示类似如下信息,表示用户正在尝试结束当前会话。 FATAL: terminating connection due to administrator command FATAL: terminating connection due to administrator command gsql客户端使用PG_TERMINATE_BACKEND函数结束当前正在执行会话的后台线程时,如果当前的用户是初始用户,客户端不会退出而是自动重连,即还会返回“The connection to the server was lost. Attempting reset: Succeeded.”;否则客户端会重连失败,即返回“The connection to the server was lost. Attempting reset: Failed.”。这是因为只有初始用户可以免密登录,普遍用户不能免密登录,从而重连失败。 对于使用PG_TERMINATE_BACKEND函数结束非活跃的后台线程时。如果打开了线程池,此时空闲的会话没有线程ID,无法结束会话。非线程池模式下,结束的会话不会自动重连。
  • 参数说明 table表示存在倾斜的单个表名。 join_rel表示参与join的两个或多个表,如(t1 t2)表示t1和t2join后的结果存在倾斜。 column表示倾斜表中存在倾斜的一个或多个列。 value表示倾斜的列中存在倾斜的一个或多个值。 skew hint仅在需要重分布且指定的倾斜信息与查询执行过程中的重分布信息相匹配时才会被使用。 skew hint目前仅处理普通表和子查询类型的表关系,支持基表hint、子查询hint、with as子句hint。对于子查询,无论提升与否都支持在skew hint中使用,这点与其它hint不一样。 对于倾斜表,如果定义了别名,则在hint中必须使用别名。 对于倾斜列,在不产生歧义的情况下,可以使用原名也可以使用别名。skew hint的column不支持表达式,如果需要指定采用分布键为表达式的重分布存在倾斜,需要将重分布键指定为新的列,以新的列进行hint。 对于倾斜值,个数需为列数的整数倍并按列的顺序进行组合,组合的个数不能超过10个。如果各倾斜列的倾斜值的个数不一样,为了满足按列组合,值可以重复指定。如,表t1的c1和c2存在倾斜,c1列的倾斜值只有a1,而c2列的倾斜有b1和b2,则skew hint如下:skew(t1 (c1 c2) ((a1 b1)(a1 b2)))。例中(a1 b1)为一个值组合,NULL可以作为倾斜值出现,每个hint中的值组合不超过十个, 且需为列的整数倍。 在Join的重分布优化中,skew hint中的value不可缺省,在HashAgg中可以缺省。 对于表、列、值中若指定多个,则同类间需以空格分离。 对于倾斜值,不支持在hint中进行类型强转;对于string类型,需要使用单引号。 例如: 指定单表倾斜 每一个skew hint用来表示一个表关系存在的倾斜信息,如果想要指定在查询中的多个表关系存在的倾斜信息,则通过指定多个skew hint实现。 在指定skew时,包括以下四个场景的用法: 单列单值: skew(t (c1) (v1)) 说明:表关系t的c1列中的v1值在查询执行中存在倾斜。 单列多值:skew(t (c1) (v1 v2 v3 ...)) 说明:表关系t的c1列中的v1、v2、v3…等值在查询执行中存在倾斜。 多列单值:skew(t (c1 c2) (v1 v2)) 说明:表关系t的c1列的v1值和c2列的v2值在查询执行中存在倾斜。 多列多值:skew(t (c1 c2) ((v1 v2) (v3 v4) (v5 v6) ...)) 说明:表关系t的c1列的v1、v3、v5…值和c2列的v2、v4、v6…值在查询执行中存在倾斜。 多列多值时,各组倾斜值间也可以不使用括号,如:skew(t (c1 c2) (v1 v2 v3 v4 v5 v6 ...))。是否使用括号必须统一,不可混合, 如:skew(t (c1 c2) (v1 v2 v3 v4 (v5 v6) ...)) 将会产生语法报错。 指定中间结果倾斜 如果基表不存在倾斜,而是查询执行中的中间结果出现倾斜,则需要通过指定中间结果倾斜的skew hint来进行倾斜的调优。skew((t1 t2) (c1) (v1)) 说明:表关系t1和t2 Join后的结果存在倾斜,倾斜的是t1表的c1列,c1列的倾斜值是v1。 为了避免产生歧义,“c1”只能存在于join_rel的一个表关系中,如果存在同名列则通过别名进行规避。
  • 示例 对示例中原语句使用如下hint: explain select /*+ no redistribute(store_sales store_returns item store) leading(((store_sales store_returns item store) customer)) */ i_product_name product_name ... 原计划中,(store_sales store_returns item store)和customer做join时,前者做了重分布,此hint表示禁止前者混合表做重分布,但仍然保持join顺序,则生成计划如下所示:
  • 使用分区表 分区表是把逻辑上的一张表根据某种方案分成几张物理块进行存储。这张逻辑上的表称之为分区表,物理块称之为分区。分区表是一张逻辑表,不存储数据,数据实际是存储在分区上的。分区表和普通表相比具有以下优点: 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索效率。 增强可用性:如果分区表的某个分区出现故障,表在其他分区的数据仍然可用。 方便维护:如果分区表的某个分区出现故障,需要修复数据,只修复该分区即可。 GaussDB支持的分区表为范围分区表。 范围分区表:将数据基于范围映射到每一个分区。这个范围是由创建分区表时指定的分区键决定的。分区键经常采用日期,例如将销售数据按照月份进行分区。 父主题: 审视和修改表定义
  • 事务 在GTM-FREE模式下,不允许执行跨节点事务。 在GTM-FREE模式下,如果所执行的SQL语句包含跨节点事务,会报错处理。 如果语句拆分多条会报错: INSERT/UPDATE/DELETE/MERGE contains multiple remote queries under GTM-free modeUnsupport DML two phase commit under gtm free mode. modify your SQL to generate light-proxy or fast-query-shipping plan。 此时需要修改语句,来单节点执行。 如果语句涉及多节点会报错: Your SQL needs more than one datanode to be involved in. 建议对语句进行修改,使得能够单节点执行。如果需要此种语句多节点执行,需要添加一个hint来允许,例如:insert /*+ multinode */ into t values(3,3),(1,1); 建议开发阶段在jdbc连接串内设置application_type=perfect_sharding_type,这样所有跨节点读写操作的SQL都会报错,用来提示开发人员尽早优化语句。 大对象操作不支持事务。 大对象操作包括:创建删除DATABASE, ANALYZE, VACUUM。 通过JDBC接入数据库时,避免拼接多条SQL为一条语句发送执行。 当多条语句拼接为一条语句,且其中包含对象操作时,如果中间对象操作失败,会重新开启新事务执行后续语句。 示例:不符合规则语句 Connection conn = .... try { Statement stmt = null; try { stmt = conn.createStatement(); stmt.executeUpdate("CREATE TABLE t1 (a int); DROP TABLE t1"); } finally { stmt.close(); } conn.commit(); } catch(Exception e) { conn.rollback(); } finally { conn.close(); } 上述执行语句,如果“CREATE TABLE t1;”失败,会重新开启新事务执行“DROP TABLE t1;”导致执行失败。应拆分成两条语句分别发送: Connection conn = .... try { Statement stmt = null; try { stmt = conn.createStatement(); stmt.executeUpdate("CREATE TABLE t1 (a int)"); stmt.executeUpdate("DROP TABLE t1"); } finally { stmt.close(); } conn.commit(); } catch(Exception e) { conn.rollback(); } finally { conn.close(); } 父主题: 数据库编程规范
  • 函数/存储过程设计规范 避免使用存储过程、触发器等实现业务逻辑,应该将这些逻辑都放到业务服务器上处理,避免对数据库产生逻辑依赖。 业务的数据库升级脚本中,禁止使用存储过程实现升级逻辑。 仅创建对固定入参有固定返回值的函数,函数必须设为IMMUTABLE和SHIPPABLE类型。 目前数据库支持三种类型的函数,分别是IMMUTABLE, STABLE, VOLATILE。 对于IMMUTABLE函数且设置为SHIPPABLE的函数,会允许函数在DN上执行。在大部分场景下,该函数的执行效率较高。 但是此类函数要求对于固定的入参得到固定的返回值,来保证函数在DN上执行的正确性。如果函数的结果依赖对数据表的扫描结果(例如获取某个表中列的max值)或依赖时间(如获取当前时间),那么函数应设置为STABLE或者VOLATILE,且NOT SHIPPABLE,以保证函数执行的正确性。在此种场景下,所有DN上的数据将发送至某一个CN上进行计算,导致查询执行效率低下。 父主题: 数据库设计规范
  • 连接与认证 session_timeout 表明与服务器建立连接后,不进行任何操作一定时间后超时的限制,0表示关闭超时设置。 failed_login_attempts 设置密码错误次数上限,输入密码错误的次数达到该参数所设置的值时,账户将会被自动锁定,配置为0时表示不限制密码输入错误的次数。 password_effect_time 设置账户密码的有效时间,0表示不开启有效期限制功能。 password_lock_time 设置账户被锁定后的自动解锁时间,单位为天。
  • 查询 track_stmt_session_slot 作用:设置一个session缓存的最大的全量/慢SQL的数量。 影响:缓存的SQL定期会被写入到系统表,如果业务量很大,超过这个数量语句执行将不会被跟踪,直到落盘线程将缓存语句落盘,留出空闲的空间,但不影响SQL的执行。 effective_cache_size 作用:设置节点优化器在一次单一的查询中可用的磁盘缓冲区的有效大小。设置这个参数,还要考虑的共享缓冲区以及内核的磁盘缓冲区。另外,还要考虑预计的在不同表之间的并发查询数目,因为它们将共享可用的空间。这个参数对分配的共享内存大小没有影响,它也不会使用内核磁盘缓冲,它只用于估算。数值是用磁盘页来计算的,通常每个页面是8192字节。 取值范围:整型,1~INT_MAX,单位为8KB。 影响:比默认值高的数值可能会导致使用索引扫描,更低的数值可能会导致选择顺序扫描。 enable_stream_operator 控制优化器对stream的使用。当该参数关闭时,可能会有大量关于计划不能下推的日志记录到日志文件中。 log_min_duration_statement 作用:当某条语句的持续时间大于或者等于特定的毫秒数时,记录每条完成语句的持续时间。设置log_min_duration_statement可以很方便地跟踪需要优化的查询语句。对于使用扩展查询协议的客户端,语法分析、绑定、执行每一步所花时间被独立记录。 影响:设置过低的阈值可能影响负载吞吐,-1表示关闭此功能。
  • 审计参数 audit_system_object 作用:该参数决定是否对数据库对象的CREATE、DROP、ALTER操作进行审计。数据库对象包括DATABASE、USER、SCHEMA、TABLE等。通过修改该配置参数的值,可以只审计需要的数据库对象的操作,在主备强制选主场景建议audit_system_object取最大值,所有DDL对象全部审计。 影响:不当修改该参数会导致丢失DDL审计日志,请在客服人员指导下进行修改。
  • 数据库设计规范 使用JDBC客户端连接数据库时必须指明数据库名,具体格式为: jdbc:postgresql://host:port/database?param1=value1¶m2=value2 JDBC实例一旦创建,无法进行数据库切换。 数据库目前不支持不区分大小写的排序方式。 目前仅支持对数据库定义字符集,不支持对表、字段等其他对象定义字符集。 业务使用前必须先创建业务数据库。 不应使用数据库安装后默认创建的postgres数据库存储业务数据。 创建数据库时必须指定字符集为UTF8,创建数据库时必须选择与客户端统一的编码字符集。 为了使用全球化需求,数据库编码应能够存储与标识绝大多数的字符,因此推荐使用UTF8。GaussDB中的UTF8字符集与MySQL的UTF8MB4等价,能够支持emoji表情字符。 如果客户端的编码方式与数据库的编码方式不统一,会带来转码性能,同时,针对同编码的内核优化无法触发,影响查询效率。 客户端的编码字符集需通过以下方式修改: 设置客户端连接参数,例如JDBC连接参数可通过在URL中追加characterEncoding和allowEncodingChanges参数。 jdbc:postgresql://ip:port/database_name?characterEncoding=utf8&allowEncodingChanges=true 修改数据库GUC参数。 SET client_encoding = 'UTF8'; 数据库的编码在CREATE DATABASE时进行设置。 CREATE DATABASE tester WITH ENCODING = 'UTF8'; 数据库一旦创建无法更改字符集。 从便捷性和资源共享效率上考虑,建议使用SCHEMA进行业务隔离。 GaussDB可以使用DATABASE和SCHEMA两种方式实现业务的隔离。 区别在于DATABASE的隔离更加彻底,各个DATABASE之间共享资源极少,可实现连接隔离、权限隔离等。 但DATABASE之间无法互相访问,JDBC建连时必须指明DATABASE,连接后无法切换DATABASE。 SCHEMA隔离的方式共用资源较多,可以通过GRANT与REVOKE语法便捷地控制不同用户对各SCHEMA及其下属对象的权限。 创建数据库时建议指定LC_COLLATE和LC_CTYPE和存放的数据内容语言(中文\英文\等等)一致,该参数将影响数据的排序顺序。默认会用系统当前环境变量的默认设置。 示例: CREATE DATABASE tester WITH ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; LC_COLLATE:用于明确字符排序规则。 LC_COLLATE=C 1 2 3 A B C a --注:小写在大写后面,按ASCII码排序 b c en_US.UTF-8 1 2 3 a --注:按字符排序 A b B c C zh_CN.UTF-8 1 2 3 a A b B c C LC_CTYPE:用于判断哪些是字符is_alpha,是大写is_upper还是小写is_lower。 父主题: 数据库设计规范
  • 操作步骤 收集SQL中涉及到的所有表的统计信息。在数据库中,统计信息是规划器生成计划的源数据。没有收集统计信息或者统计信息陈旧往往会造成执行计划严重劣化,从而导致性能问题。从经验数据来看,10%左右性能问题是因为没有收集统计信息。具体请参见更新统计信息。 通过查看执行计划来查找原因。如果SQL长时间运行未结束,通过EXPLAIN命令查看执行计划,进行初步定位。如果SQL可以运行出来,则推荐使用EXPLAIN ANALYZE或EXPLAIN PERFORMANCE查看执行计划及实际运行情况,以便更准确地定位问题原因。有关执行计划的详细介绍请参见SQL执行计划介绍。 审视和修改表定义。 针对EXPLAIN或EXPLAIN PERFORMANCE信息,定位SQL慢的具体原因以及改进措施,具体参见典型SQL调优点。 通常情况下,有些SQL语句可以通过查询重写转换成等价的,或特定场景下等价的语句。重写后的语句比原语句更简单,且可以简化某些执行步骤达到提升性能的目的。查询重写方法在各个数据库中基本是通用的。经验总结:SQL语句改写规则介绍了几种常用的通过改写SQL进行调优的方法。
  • 告警场景 目前支持对以下7种导致性能问题的场景上报告警。 多列/单列统计信息未收集 如果存在单列或者多列统计信息未收集,则上报相关告警。调优方法可以参考更新统计信息和统计信息调优。 需要特别注意的是,对于基于OBS外表的查询,如果未收集统计信息也会上报统计信息未收集的告警,但是由于OBS外表的analyze的性能比较差,因此,需要用户对这种场景下告警是否通过analyze收集统计信息,以获取更优的性能,和查询本身的复杂度做权衡。 告警信息示例: 整表的统计信息未收集: Statistic Not Collect: schema_test.t1 单列统计信息未收集: Statistic Not Collect: schema_test.t2(c1,c2) 多列统计信息未收集: Statistic Not Collect: schema_test.t3((c1,c2)) 单列和多列统计信息未收集: Statistic Not Collect: schema_test.t4(c1,c2) schema_test.t4((c1,c2)) SQL不下推 对于不下推的SQL,尽可能详细上报导致不下推的原因。调优方法可以参考案例语句下推调优。 对于函数导致的不下推,告警导致不下推的函数名信息; 对于不支持下推的语法,会告警对应语法不支持下推,例如:含有With Recursive,Distinct On,row表达式,返回值为record类型的,会告警相应语法不支持下推等等。 告警信息示例: SQL is not plan-shipping, reason : "With Recursive" can not be shipped" SQL is not plan-shipping, reason : "Function now() can not be shipped" SQL is not plan-shipping, reason : "Function string_agg() can not be shipped" HashJoin中大表做内表 如果在表连接过程中使用了HashJoin(可以在GS_WLM_SESSION_HISTORY视图的query_plan字段中查看到),且连接的内表行数是外表行数的10倍或以上;同时内表在每个DN上的平均行数大于10万行,且发生了下盘,则上报相关告警。调优方法可以参考使用Plan Hint进行调优。 告警信息示例: PlanNode[7] Large Table is INNER in HashJoin “Vector Hash Aggregate” 大表等值连接使用Nestloop 如果在表连接过程中使用了nestloop(可以在GS_WLM_SESSION_HISTORY视图的query_plan字段中查看到),并且两个表中较大表的行数平均每个DN上的行数大于10万行、表的连接中存在等值连接,则上报相关告警。调优方法可以参考使用Plan Hint进行调优。 告警信息示例: PlanNode[5] Large Table with Equal-Condition use Nestloop"Nested Loop" 大表Broadcast 如果在Broadcast算子中,平均每DN的行数大于10万行,则告警大表broadcast。调优方法可以参考使用Plan Hint进行调优。 告警信息示例: PlanNode[5] Large Table in Broadcast "Streaming(type: BROADCAST dop: 1/2)" 数据倾斜 某表在各DN上的分布,存在某DN上的行数是另一DN上行数的10倍或以上,且有DN中的行数大于10万行,则上报相关告警。调优方法可以参考案例数据倾斜调优。 告警信息示例: PlanNode[6] DataSkew:"Seq Scan", min_dn_tuples:0, max_dn_tuples:524288 估算不准 如果优化器的估算行数和实际行数中的较大值平均每DN行数大于10万行,并且估算行数和实际行数中较大值是较小值的10倍或以上,则上报相关告警。调优方法可以参考使用Plan Hint进行调优。 告警信息示例: PlanNode[5] Inaccurate Estimation-Rows: "Hash Join" A-Rows:0, E-Rows:52488
  • 规格约束 告警字符串长度上限为2048。如果告警信息超过这个长度(例如存在大量未收集统计信息的超长表名,列名等信息)则不告警,只上报warning: WARNING, "Planner issue report is truncated, the rest of planner issues will be skipped" 如果query存在limit节点(即查询语句中包含limit),则不会上报limit节点以下的Operator级别的告警。 对于“数据倾斜”和“估算不准”两种类型告警,在某一个plan树结构下,只上报下层节点的告警,上层节点不再重复告警。这主要是因为这两种类型的告警可能是因为底层触发上层的。例如,如果在scan节点已经存在数据倾斜,那么在上层的hashagg等其他算子很可能也出现数据倾斜。
共100000条