华为云用户手册

  • 参考标准和协议 与VPN相关的参考标准与协议如下: RFC 2403: The Use of HMAC-MD5-96 within ESP and AH RFC 2404: The Use of HMAC-SHA-1-96 within ESP and AH RFC 2409: The Internet Key Exchange (IKE) RFC 2451: The ESP CBC-Mode Cipher Algorithms RFC 3526: More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE) RFC 3566: The AES-XCBC-MAC-96 Algorithm and Its Use With IPsec RFC 3602: The AES-CBC Cipher Algorithm and Its Use with IPsec RFC 3664: The AES-XCBC-PRF-128 Algorithm for the Internet Key Exchange Protocol (IKE) RFC 4106: The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating Security Payload (ESP) RFC 4109: Algorithms for Internet Key Exchange version 1 (IKEv1) RFC 4434: The AES-XCBC-PRF-128 Algorithm for the Internet Key Exchange Protocol (IKE) RFC 4868: Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with IPsec RFC 4301: Security Architecture for the Internet Protocol RFC 4302: IP Authentication Header RFC 4303: IP Encapsulating Security Payload (ESP) RFC 4305: Cryptographic Algorithm Implementation Requirements for Encapsulating Security Payload (ESP) and Authentication Header (AH) RFC 4306: Internet Key Exchange (IKEv2)Protocol RFC 4307: Cryptographic Algorithms for Use in the Internet Key Exchange Version 2 (IKEv2) RFC 4308: Cryptographic Suites for IPsec RFC 5282: Using Authenticated Encryption Algorithms with the Encrypted Payload of the Internet Key Exchange version 2 (IKEv2) Protocol RFC 6989: Additional Diffie-Hellman Tests for the Internet Key Exchange Protocol Version 2 (IKEv2) RFC 7296: Internet Key Exchange Protocol Version 2 (IKEv2) RFC 7321: Cryptographic Algorithm Implementation Requirements and Usage Guidance for Encapsulating Security Payload (ESP) and Authentication Header (AH) RFC 8247: Algorithm Implementation Requirements and Usage Guidance for the Internet Key Exchange Protocol Version 2 (IKEv2) RFC 3947: Negotiation of NAT-Traversal in the IKE RFC 3948: UDP Encapsulation of IPsec ESP Packets RFC 3706: A Traffic-Based Method of Detecting Dead Internet Key Exchange (IKE) Peers RFC 4271: A Border Gateway Protocol 4 (BGP-4)
  • GUC参数编程规范 客户端(如JDBC)应使用默认(全局)参数执行查询,禁用会话级别的GUC参数。 通过ODBC或JDBC修改GUC参数时,需注意GUC参数仅会在当前connection中生效,特别是在连接池场景下,容易发生问题,且导致问题定位困难。 如果在连接中必须进行GUC参数设置,那么在将连接归还给连接池之前,必须使用 SET SESSION AUTHORIZATION DEFAULT; RESET ALL; 将连接的状态清空。 父主题: 数据库编程规范
  • INSERT INSERT ON DUPLICATE KEY UPDATE不支持对主键或唯一约束的列上执行UPDATE。 INSERT ON DUPLICATE KEY UPDATE的语义是对唯一约束冲突的行进行更新,这个过程中不应对约束的值进行更新。 INSERT ON DUPLICATE KEY UPDATE如果插入多条数据,这些数据之间不允许存在主键/唯一约束冲突。 与MySQL行为存在一定差异,MYSQL允许此行为,例如如下语句: INSERT INTO t1 VALUES(1, 1), (1, 2) ON DUPLICATE KEY UPDATE col2 = VALUES(col2); 不符合SQL标准,SQL标准不允许在同一条SQL COMMAND中,对插入行同时进行修改,使得结果无可预期。例如上例中,假设col1为主键,那么此时会在同一个COMMAND中,既插入一条主键为1的,同时对已插入进行修改。由于事务串行化无法确认哪一个操作先执行,因此可能导致结果不稳定。 如果插入的数据本身存在冲突,在分布式场景下更新应以哪一条记录为准难以确定。 禁止对存在多个唯一约束的表执行INSERT ON DUPLICATE KEY UPDATE。 表中存在多个唯一约束包括存在多个唯一索引,或既存在主键(PRIMARY KEY),又存在唯一索引(UNQUE INDEX)两种情况。 当存在多个唯一约束时,会默认检查所有的唯一约束条件,只要任何一个约束存在冲突,就会对冲突行进行更新,即可能更新多条记录,与业务预期不相符。业务应给予更加明确的插入更新条件。 对于批量插入的情况,建议使用INSERT INTO TABLE1 VALUES (),(),(),执行效率将高于执行多条INSERT INTO VALUES() 由于目前无法识别多个值是否属于一个shard,所以要使用/*+ multinode */ 来允许此语句执行。 无论单条和多条插入,关键字均需是VALUES。 不支持MySQL的INSERT INTO mytable VALUE()的用法。 父主题: 数据库编程规范
  • DELETE 不支持DELETE语句中使用LIMIT。应使用WHERE条件明确需要更新的目标行。 在GMT-FREE模式下,不允许跨节点事务,因此删除HASH分布表中数据时,必须在WHERE条件中指定分布列等值过滤条件。 不支持多表删除。 多表删除即在单条SQL语句中,对多个表进行删除。 DELETE语句中必须有WHERE子句,避免全表扫描。 DELETE语句中禁止不应使用ORDER BY、GROUP BY子句,避免不必要的排序。 如果需要清空一张表,建议使用TRUNCATE,而不是DELETE。 TRUNCATE会创建新的物理文件,并在事务结束时将原文件物理删除,清空磁盘空间。而DELETE会将表中数据进行标记,直到VACCUUM FULL阶段才会真正清理磁盘空间。 DELETE有主键或索引的表,WHERE条件应结合主键或索引,提高执行效率。 父主题: 数据库编程规范
  • 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条件应结合主键/索引。 父主题: 数据库编程规范
  • 索引设计规范 使用数据库索引实践推荐的索引类型。 索引设计建议使用推荐类型,如果需要使用禁用、不推荐、限制使用的索引类型,建议联系 GaussDB数据库 专家进行评估。 表1 数据库索引实践推荐 索引类型 说明 是否推荐 主键/唯一索引 单列或多列主键/唯一索引 推荐 表达式索引 索引列为表的一列或多列计算而来的一个函数或者标量表达式 限制使用 对于HASH分布表,主键和唯一索引必须包含分布键。 合理设计组合索引,避免冗余。 例如已对(a,b,c)创建索引,则不应再单独对 (a)、(b)、(c)、(a,b)、(b,c)创建索引。 当查询时如果只带有a字段上的过滤条件,一般也会利用组合索引进行查询。 不建议单表创建多个唯一索引。 同时维护多个唯一索引的开销远大于维护一个多列唯一索引,如果业务逻辑上多个唯一索引,与一个多列唯一索引等价,应使用多列唯一索引。 组合索引字段个数不超过5个。 禁止组合索引组合字符串的总长度超过200。 索引(包括单列索引和复合索引)字段应为NOT NULL字段。 同字段上创建索引的维护效率不同。数值类型字段优于字符类型及其他数据类型,因此对于考虑创建索引的ID、时间等字段,建议使用数值类型进行存储。 建议在关联列上创建索引。 GaussDB支持HASH JOIN,但是当内表较小等RESCAN代价较低的情况下,仍然可能选择NESTLOOP JOIN来完成关联。如果通过EXPLAIN可以查看到NESTLOOP JOIN计划,则可以通过在关联列上创建索引,提高NESTLOOP JOIN效率。 父主题: 数据库设计规范
  • 表设计规范 必须指定表分布(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。 父主题: 数据库设计规范
  • 关联查询 多表关联嵌套深度必须小于8。 关联嵌套过深,容易产生慢sql,应从业务层考虑优化。 表关联查询必须明确指定各表的连接条件(ON),以避免产生笛卡尔积。 例如在MySQL中,JOIN与CROSS JOIN和INNER JOIN等价,但是在SQL标准中,JOIN仅与INNER JOIN等价,必须配合使用ON连接条件。 反例:如下2个示例会造成笛卡尔积查询 SELECT * FROM TABLE1 A , TABLE2 B; SELECT * FROM TABLE1 A JOIN TABLE2 B ON 1=1; 关联时,应该根据SQL标准指明连接方式,避免直接使用JOIN关键词,而是使用CROSS JOIN, INNER JOIN, LEFT JOIN, RIGHT JOIN等。 多表关联查询时, 必须应对表添加使用别名,保证语句逻辑清晰,便于维护。 不同字段的比较开销不同,关联字段应尽量使用比较效率高的字段类型。 数值类型的比较效率远高于字符串类型。 在数值类型中,整型效率高于NUMERIC和浮点类型。 关联字段应为相同数据类型,避免存在隐式类型转换影响执行效率。 少用嵌套子查询,尽量使用表关联,因为子查询会产生临时表,对SQL性能影响较大。 对于关联列上存在大量NULL值的情况,建议在WHERE条件中增加关联列IS NOT NULL的过滤条件,能够提升执行效率。 父主题: 数据库编程规范
  • 函数/存储过程设计规范 避免使用存储过程、触发器等实现业务逻辑,应该将这些逻辑都放到业务服务器上处理,避免对数据库产生逻辑依赖。 业务的数据库升级脚本中,禁止使用存储过程实现升级逻辑。 仅创建对固定入参有固定返回值的函数,函数必须设为IMMUTABLE和SHIPPABLE类型。 目前数据库支持三种类型的函数,分别是IMMUTABLE, STABLE, VOLATILE。 对于IMMUTABLE函数且设置为SHIPPABLE的函数,会允许函数在DN上执行。在大部分场景下,该函数的执行效率较高。 但是此类函数要求对于固定的入参得到固定的返回值,来保证函数在DN上执行的正确性。如果函数的结果依赖对数据表的扫描结果(例如获取某个表中列的max值)或依赖时间(如获取当前时间),那么函数应设置为STABLE或者VOLATILE,且NOT SHIPPABLE,以保证函数执行的正确性。在此种场景下,所有DN上的数据将发送至某一个CN上进行计算,导致查询执行效率低下。 父主题: 数据库设计规范
  • 资源评估规范 基于表1模板估算台账,资源利用率尽量控制在40%-70%间,低40%建议缩容,高于70%建议扩容。 表1 GaussDB上线台账 组件 规格一 规格二 规格三 规格四 规格五 MEM/CPU 文件 磁盘容量 备注 CN 8C64G 16C128G 32C256G ARM:60C480G X86:64C512G / 8 /var/chroot/var/lib/log 64G 日志盘 /var/chroot/usr/local 256G 数据盘 DN 8C64G 16C128G 32C256G ARM:60C480G X86:64C512G / 8 /var/chroot/var/lib/log 64G 日志盘 /var/chroot/var/lib/engine/data 3788G 数据盘 /var/chroot/var/lib/log/backup 20G 备份会把元数据信息放一份到这个盘上 GTM 4C32G 8C64G 16C128G 32C256G ARM:60C480G X86:64C512G 8 /var/chroot/var/lib/log 32G 日志盘 1-9分片 9-16分片 16-32分片 32-64分片 64分片以上 /var/chroot/usr/local 32G 数据盘 CMS+ETCD 4C32G 8C64G 16C128G 32C256G ARM:60C480G X86:64C512G 8 /var/chroot/var/lib/log 32G 日志盘 1-9分片 9-16分片 16-32分片 32-64分片 64分片以上 /var/chroot/usr/local 64G 数据盘
  • 权限设计规范 业务使用前必须由root用户为业务创建DATABASE、SCHEMA和USER,然后再赋予相关用户对应对象的权限。 如果该用户不是该schema的owner,要访问schema下的对象,需要同时给用户赋予schema的usage权限和对象的相应权限。 DATABASE、SCHEMA和USER名使用小写。 由于数据库默认会把对象名称转为小写,连接串里面如果出现大写的对象名无法连接到数据库。如create user MyUser;创建的用户,无法使用user=MyUser连接到数据库,需要用user=myuser才能连接到数据库。为了避免混淆,一律使用小写。 合理对角色和用户赋权,应使用最小化权限原则。 表1 数据库对象权限及说明 对象 权限 说明 数据库 DATABASE CONNECT 允许用户连接到指定的数据库 TEMP - CREATE 允许在数据库里创建新的模式 模式 SCHEMA CREATE 允许在模式中创建新的对象 USAGE 允许访问包含在指定模式中的对象,若没有该权限,则只能看到这些对象的名字。 函数 FUNCTION EXECUTE 允许使用指定的函数,以及利用这些函数实现的操作符 表空间 TABLESPACE CREATE 允许在表空间中创建表,允许在创建数据库和模式的时候把该表空间指定为缺省表空间。 表 TABLE INSERT,DELETE UPDATE,SELECT 允许用户对指定表进行增删改查操作 TRUNCATE 允许执行TRUNCATE语句删除指定表中的所有记录。 REFEREN CES 创建一个外键约束,必须拥有参考表和被参考表的REFERENCES权限 通过角色而不是用户来管理权限。 使用角色管理权限,即在角色中配置权限,再将角色赋予用户。 通过角色管理权限,更便于多用户、用户变更等场景下的权限管理。例如: 角色和用户为多对多关系,一个角色可以赋予多个用户,修改角色中的权限,被赋予角色的用户权限就可以同时更新。 删除用户时,不会影响到角色。 新建用户后可以通过赋予角色快速获取所需权限。 在删除指定数据库时,应回收用户对该数据库的CONNECT权限,避免删除时仍然存在活跃的数据库连接而失败。 父主题: 数据库设计规范
  • 数据库特性规范 表1 数据库价值特性推荐 特性分类 特性列表 说明 表类型 HASH分布表 自动分片的表,建议数据量大的表使用(如交易记录)。 REPLICATE分布表 不分片的普通表,建议数据少的表使用(如国家名称表)。 事务 分布式事务(弱一致) GTM Free模式,在sharding场景下可保证强一致,不保证跨DN分片读一致性。建议完美sharding业务使用。 分布式事务(强一致) GTM Lite模式,保证跨DN读写一致性,建议非完美sharding业务使用。 扩容 在线平滑扩容 在线业务的最大阻塞小于5s,主要是为了追增切换期间写入日志,扩容速度100G/小时。 部署 3AZ3副本 建议默认采用3AZ3副本部署。 数据类型 整数类型 TINYINT, SMALLINT, INTEGER, BIGINT 任意精度类型 NUMERIC/DEMICAL 浮点类型 REAL/FLOAT4,DOUBLE PRECISION/FLOAT8,FLOAT 布尔类型 BOOLEAN 定长字符 CHAR(n) 变长字符 VARCHAR(n),NVARCHAR2(n), TEXT 时间类型 DATE, TIME, TIMETZ, TIMESTAMP, TIMESTAMPTZ, SMALLDATETIME, INTERVAL, REALTIME 二进制类型 BYTEA(变长二进制类型) 位串类型 BIT(n), VARBIT(n) 函数 字符处理函数 字符类数据类型处理函数 二进制字符串函数 二进制字符类型处理函数 数字操作函数 数值类型处理函数 时间和日期处理函数 时间和日期类型处理函数 索引 主键/唯一索引 单列或多列主键/唯一索引 BTREE索引 索引类型 未包含在价值列表中的特性(包括但不限于自定义,UUID等数据类型,触发器等特性),如需使用建议联系GaussDB 数据库技术人员进行评估。
  • 注意事项 因为安全组的默认规则是在出方向上的数据报文全部放行,同一个安全组内的弹性云服务器和GaussDB实例可互相访问。安全组创建后,您可以在安全组中定义各种访问规则,当GaussDB实例加入该安全组后,即受到这些访问规则的保护。 默认情况下,一个租户可以创建500条安全组规则。 建议一个安全组内的安全组规则不超过50条。 当需要从安全组外访问安全组内的GaussDB实例时,需要为安全组添加相应的入方向规则。 分组名称不能重复。 为了保证数据及实例安全,请合理使用权限。建议使用最小权限访问,同时将可访问IP地址设置为远程主机地址或远程主机所在的最小子网地址,限制远程主机的访问范围。 源地址默认的IP地址0.0.0.0/0是指允许所有IP地址访问安全组内的GaussDB实例。 关于添加安全组规则的详细要求,可参考《虚拟私有云用户指南》的“添加安全组规则”章节。
  • 优化分析2 在以上查询中,supplier、lineitem、partsupp三表做hashjoin的条件为(lineitem.l_suppkey = supplier.s_suppkey) AND (lineitem.l_partkey = partsupp.ps_partkey),此hashjoin条件中存在两个过滤条件,这前一个过滤条件中的lineitem.l_suppkey和后一个过滤条件中的lineitem.l_partkey同为lineitem表的两列,这两列存在强相关的关联关系。在这种情况,估算hashjoin条件的选择率时,如果使用cost_param的bit1为0时,实际是将AND的两个过滤条件分别计算的2个选择率的值相乘来得到hashjoin条件的选择率,导致行数估算不准确,查询性能较差。所以需要将cost_param的bit1为1时,选择最小的选择率作为总的选择率估算行数比较准确,查询性能较好,优化后的计划如下图所示:
  • 现象描述2 当cost_param的bit1(set cost_param=2)为1时,表示求多个过滤条件(Filter)的选择率时,选择最小的作为总的选择率,而非两者乘积,此方法在过滤条件的列之间关联性较强时估算更加准确。下面查询的例子是cost_param的bit1为1时的优化场景。 表结构如下所示: 1 2 3 4 5 6 7 8 910111213141516171819202122232425 CREATE TABLE NATION( N_NATIONKEY INT NOT NULL, N_NAME CHAR(25) NOT NULL, N_REGIONKEY INT NOT NULL, N_COMMENT VARCHAR(152)) distribute by replication;CREATE TABLE SUPPLIER( S_SUPPKEY BIGINT NOT NULL, S_NAME CHAR(25) NOT NULL, S_ADDRESS VARCHAR(40) NOT NULL, S_NATIONKEY INT NOT NULL, S_PHONE CHAR(15) NOT NULL, S_ACCTBAL DECIMAL(15,2) NOT NULL, S_COMMENT VARCHAR(101) NOT NULL) distribute by hash(S_SUPPKEY);CREATE TABLE PARTSUPP( PS_PARTKEY BIGINT NOT NULL, PS_SUPPKEY BIGINT NOT NULL, PS_AVAILQTY BIGINT NOT NULL, PS_SUPPLYCOST DECIMAL(15,2)NOT NULL, PS_COMMENT VARCHAR(199) NOT NULL)distribute by hash(PS_PARTKEY); 查询语句如下所示: 1 2 3 4 5 6 7 8 910111213141516171819202122 set cost_param=2;explain verbose selectnation,sum(amount) as sum_profit from(selectn_name as nation,l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amountfromsupplier,lineitem,partsupp,nationwheres_suppkey = l_suppkeyand ps_suppkey = l_suppkeyand ps_partkey = l_partkeyand s_nationkey = n_nationkey) as profit group by nation order by nation; 当cost_param的bit1为0时,执行计划如下图所示:
  • 数据库设计规范 使用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=C123ABCa --注:小写在大写后面,按ASCII码排序bc en_US.UTF-8123a --注:按字符排序AbBcC zh_CN.UTF-8123aAbBcC LC_CTYPE:用于判断哪些是字符is_alpha,是大写is_upper还是小写is_lower。 父主题: 数据库设计规范
  • 优化分析 如果将a作为t1和t2的分布列: 12 CREATE TABLE t1 (a int, b int) DISTRIBUTE BY HASH (a);CREATE TABLE t2 (a int, b int) DISTRIBUTE BY HASH (a); 则执行计划将存在“Streaming”,导致DN之间存在较大通信数据量,如图1所示。 图1 选择合适的分布列案例(一) 如果将a作为t1的分布列,将b作为t2的分布列: 12 CREATE TABLE t1 (a int, b int) DISTRIBUTE BY HASH (a);CREATE TABLE t2 (a int, b int) DISTRIBUTE BY HASH (b); 则执行计划将不包含“Streaming”,减少DN之间存在的通信数据量,从而提升查询性能,如图2所示。 图2 选择合适的分布列案例(二)
  • 优化分析 上述两个特征表明了此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(如下图)中可以看出各个节点的内存资源消耗也存在极为严重的偏斜。
  • 示例 对示例中原语句使用如下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的错误、冲突及告警的说明。
  • 现象描述 查询所有员工的信息: 1234567 SELECT staff_id,first_name,last_name,employment_id,state_name,city FROM staffs,sections,states,places WHERE sections.section_name='Sales' AND staffs.section_id = sections.section_id AND sections.place_id = places.place_id AND places.state_id = states.state_id ORDER BY staff_id;
  • 术语约定 本规范采用以下的术语描述: 规格:数据库规格,编程、设计必须遵守的原则,否则数据库将报错。 规则:编程、设计强制必须考虑遵守的原则。 建议:编程、设计必须推荐加以考虑的原则。 说明:对规则或建议进行必要的解释。 示例:对规则或建议进行或正或反方面的举例。 分片:将一个表中的数据按照指定的策略拆分并存储至多个DN上的同名表中,这些表中存储的数据互不重叠,可以理解为“表的水平分库”,举例:t_user表按主键userId Hash拆分到GaussDB的4个不同DN中就是4个分片,每个分片内都有一张同名的t_user表。
  • 参数说明 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做内表。
  • 参数说明 table表示为该子链接块hint的别名的名称。 blockname hint仅在对应的子链接块提升时才会被上层查询使用。目前支持的子链接提升包括IN子链接提升、EXISTS子链接提升和包含Agg等值相关子链接提升。该hint通常会和前面章节提到的hint联合使用。 对于FROM关键字后的子查询,则需要使用子查询的别名进行hint,blockname hint不会被用到。 如果子链接中含有多个表,则提升后这些表可与外层表以任意优化顺序连接,hint也不会被用到。
  • 示例 explain select /*+nestloop(store_sales tt) */ * from store_sales where ss_item_sk in (select /*+blockname(tt)*/ i_item_sk from item group by 1); 该hint表示:子链接的别名为tt,提升后与上层的store_sales表关联时使用nestloop。生成计划如下所示:
  • 参数说明 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的一个表关系中,如果存在同名列则通过别名进行规避。
  • Plan Hint实际调优案例 本节以TPC-DS标准测试的Q24的部分语句为例,在1000X,24DN环境上,说明使用plan hint进行实际调优的过程。示例如下: select avg(netpaid) from (select c_last_name ,c_first_name ,s_store_name ,ca_state ,s_state ,i_color ,i_current_price ,i_manager_id ,i_units ,i_size ,sum(ss_sales_price) netpaid from store_sales ,store_returns ,store ,item ,customer ,customer_address where ss_ticket_number = sr_ticket_number and ss_item_sk = sr_item_sk and ss_customer_sk = c_customer_sk and ss_item_sk = i_item_sk and ss_store_sk = s_store_sk and c_birth_country = upper(ca_country) and s_zip = ca_zip and s_market_id=7 group by c_last_name ,c_first_name ,s_store_name ,ca_state ,s_state ,i_color ,i_current_price ,i_manager_id ,i_units ,i_size); 该语句的初始计划如下,运行时间110s: 该计划中,第10层算子使用broadcast性能较差,由于第11层算子估算行数为2140,比实际行数严重低估。错误行数估算主要来源于第13层算子的行数低估,根因是第13层hashjoin中,使用store_sales的(ss_ticket_number, ss_item_sk)列和store_returns的(sr_ticket_number, sr_item_sk)列进行关联,由于缺少多列相关性的估算导致行数严重低估。 2. 使用如下的rows hint进行调优后,计划如下,运行时间318s: select avg(netpaid) from (select /*+rows(store_sales store_returns * 11270)*/ c_last_name ... 时间反而劣化了,原因是第8层hashjoin过慢引起第9层redistribute时间过慢导致,其中第9层redistribute并没有数据倾斜,hashjoin慢的原因是由于第18层redistribute后数据倾斜导致。 3. 经过实际数据查证,customer_address的两个join列的不同值数目较少,使用其进行join容易出现数据倾斜,故把customer_address放到最后进行join。使用如下的hint进行调优后,计划如下,运行时间116s: select avg(netpaid) from (select /*+rows(store_sales store_returns *11270) leading((store_sales store_returns store item customer) customer_address)*/ c_last_name ... 发现时间基本花在了第6层redistribute算子上,需要进一步优化。 4. 由于最后一层redistribute包含倾斜,所以时间较长。为了避免倾斜,需要将item表放在最后join,由于item表的join并不能使行数减少。修改hint如下并执行,计划如下,运行时间120s: select avg(netpaid) from (select /*+rows(store_sales store_returns *11270) leading((customer_address (store_sales store_returns store customer) item)) c_last_name ... 该计划中的redistribute问题并没有解决,因为第22层item表做了broadcast,导致与customer_address表join后的倾斜并没有被消除掉。 5. 增加如下禁止item表做broadcast的hint,使与customer_address join的表做redistribute(也可以进行join表redistribute的hint),计划如下,运行时间105s: select avg(netpaid) from (select /*+rows(store_sales store_returns *11270) leading((customer_address (store_sales store_returns store customer) item)) no broadcast(item)*/ c_last_name ... 6. 发现最后一层使用单层Agg,但行数缩减较多。使用相同的hint,同时结合参数best_agg_plan=3进行双层Agg调优,最终计划如下图所示,运行时间94s,完成调优。 如果有统计信息变更引起的查询劣化,可以考虑用plan hint来调整到之前的查询计划。这里以TPCH-Q17为例,在收集default_statistics_target设置为–2的统计信息之后,计划相比于默认统计信息发生劣化。 1. 默认统计信息(default_statistics_target设置为100)的计划如下: 2. 统计信息变更(default_statistics_target设置为–2)的计划如下: 3. 经过对比,劣化的原因主要为lineitem和part表join时stream类型由BroadCast变更为Redistribute导致。可以对语句进行stream方式的hint来调整到之前的计划,例如: 父主题: 使用Plan Hint进行调优
  • 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进行调优
  • 示例 本章节使用同一个语句进行示例,便于Plan Hint支持的各方法作对比,示例语句及不带hint的原计划如下所示: explain select i_product_name product_name ,i_item_sk item_sk ,s_store_name store_name ,s_zip store_zip ,ad2.ca_street_number c_street_number ,ad2.ca_street_name c_street_name ,ad2.ca_city c_city ,ad2.ca_zip c_zip ,count(*) cnt ,sum(ss_wholesale_cost) s1 ,sum(ss_list_price) s2 ,sum(ss_coupon_amt) s3 FROM store_sales ,store_returns ,store ,customer ,promotion ,customer_address ad2 ,item WHERE ss_store_sk = s_store_sk AND ss_customer_sk = c_customer_sk AND ss_item_sk = i_item_sk and ss_item_sk = sr_item_sk and ss_ticket_number = sr_ticket_number and c_current_addr_sk = ad2.ca_address_sk and ss_promo_sk = p_promo_sk and i_color in ('maroon','burnished','dim','steel','navajo','chocolate') and i_current_price between 35 and 35 + 10 and i_current_price between 35 + 1 and 35 + 15 group by i_product_name ,i_item_sk ,s_store_name ,s_zip ,ad2.ca_street_number ,ad2.ca_street_name ,ad2.ca_city ,ad2.ca_zip ;
  • 支持范围 当前版本Plan Hint支持的范围如下,后续版本会进行增强。 指定Join顺序的Hint - leading hint 指定Join方式的Hint,仅支持除semi/anti join,unique plan之外的常用hint。 指定结果集行数的Hint 指定Stream方式的Hint 指定Scan方式的Hint,仅支持常用的tablescan,indexscan和indexonlyscan的hint。 指定子链接块名的Hint 指定倾斜信息的Hint,仅支持Join与HashAgg的重分布过程倾斜。
共100000条