云服务器内容精选

  • 建议3.17 针对SQL标记注释,唯一标识SQL的归属 违反规范的影响: 业务溯源能力较差,只能通过数据库、用户名、客户端IP信息找开发人员确认。 方案建议: 建议使用query_band,例如: 1 SET query_band='JobName=abc;AppName=test;UserName=user'; 每个SQL开头标记注释,唯一标识SQL的归属,方便问题定位及应用性能分析,命名建议为: /* 模块名_工具名_作业名_步骤 */,如: /* mca_python_xxxxxx_step1 */ insert into xxx select … from
  • 建议3.10 尽量避免对关联条件字段和过滤条件字段进行函数运算 违反规范的影响: 对关联条件字段和过滤条件字段进行函数运算,导致优化器无法获取到准确的字段统计信息,无法生成最优计划,影响执行性能。 方案建议: 关联条件字段之间直接比较,需要运算后比较场景在数据入库前做好加工。 过滤条件和常量比较时,只对常量列做函数运算,字段列不做函数运算,例如: 1 2 3 4 5 6 7 8 9 SELECT id, from_image_id, from_person_id, from_video_id FROM face_data WHERE SS.DEL_FLAG = 'N' AND NVL(SS.DELETE_FLAG, 'N') = 'N' 改写为: SELECT id, from_image_id, from_person_id, from_video_id FROM face_data where SS.DEL_FLAG = 'N' AND (SS.DELETE_FLAG = 'N' or SS.DELETE_FLAG is null)
  • 操作步骤 参见创建DWS 3.0集群创建DWS 3.0集群,集群创建后默认会转换成逻辑集群v3_logical。 通过节点扩容方式增加3个节点到弹性集群,再添加逻辑集群lc2。 创建用户u1,并关联逻辑集群v3_logical。 1 CREATE USER u1 with SYSADMIN NODE GROUP "v3_logical" password "Password@123"; 创建用户u2,并关联逻辑集群lc2。 1 CREATE USER u2 with SYSADMIN NODE GROUP "lc2" password "Password@123"; 以u1登录数据库,创建表t1和t2,并插入测试数据。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CREATE TABLE public.t1 ( id integer not null, data integer, age integer ) WITH (ORIENTATION =COLUMN, COLVERSION =3.0) DISTRIBUTE BY ROUNDROBIN; CREATE TABLE public.t2 ( id integer not null, data integer, age integer ) WITH (ORIENTATION = COLUMN, COLVERSION =3.0) DISTRIBUTE BY ROUNDROBIN; INSERT INTO public.t1 VALUES (1,2,10),(2,3,11); INSERT INTO public.t2 VALUES (1,2,10),(2,3,11); 以u2登录数据库,执行以下命令查询t1和写入数据。 从结果可得出,实现用户u2跨逻辑集群进行查询和写入数据的能力。 1 2 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t2;
  • 建议3.6 避免对列存表频繁或并发执行UPDATE/DELETE 违反规范的影响: 针对列存表频繁执行UPDATE/DELETE造成CU膨胀,导致空间膨胀和访问性能下降。 针对列存表并发执行UPDATE/DELETE,导致行锁阻塞和分布式死锁风险,导致业务报错和性能下降。 方案建议: 频繁执行UPDATE/DELETE操作的表设计为行存表。 按主键或分布列进行分组UPDATE/DELETE,组间并行组内串行。
  • 规则2.3 创建DATABASE时必须选择正确的数据库兼容模式 违反规则的影响: 选错数据库兼容模式,会导致从其他厂商的数据库迁移到 GaussDB (DWS)后出现行为不一致问题,且不支持直接修改数据库兼容模式,需重新建库重新导数 方案建议: 根据源库端数据库类型,在GaussDB(DWS)中建库时通过DBCOMPATIBILITY指定兼容模式,当前支持Teradata、Oracle和MySQL等多种兼容模式。
  • 总体开发设计规范 下表是GaussDB(DWS)开发过程中需遵循的开发设计规范全集列表,可以单击链接跳转到对应的规则下了解详细说明。 表1 GaussDB(DWS)开发设计规范全集列表 编号 类别 规则/建议 1 连接管理规范 - 规则1.1 GaussDB(DWS)集群必须配置负载均衡 2 规则1.2 连接数据库完成所需操作后,必须关闭数据库连接(连接池场景除外)。 3 规则1.3 开启的事务最后必须提交或回滚 4 规则1.4 应用侧使用连接池场景,其空闲超时配置必须小于服务侧的SESSION_TIMEOUT配置 5 规则1.5 应用侧使用连接池场景,如使用连接SET设置过参数,当将连接归还连接池前,必须进行参数重置 6 规则1.6 应用侧使用连接池场景,如使用连接创建过临时表,当将连接归还连接池前,必须手动清理所创建的临时表 7 对象设计规范 DATABASE对象设计 规则2.1 避免直接使用内置的DATABASE(如postgres、gaussdb等) 8 规则2.2 创建DATABASE时必须选择正确的数据库编码 9 规则2.3 创建DATABASE时必须选择正确的数据库兼容模式 10 建议2.4 存在关联计算的对象放在同一个DATABASE中 11 USER对象设计 规则2.5 禁止使用特殊权限用户运行业务,需遵循权限最小分配原则 12 规则2.6 禁止使用一个数据库用户运行所有业务 13 SCHEMA对象设计 建议2.7 不在其他USER的私有SCHEMA下创建对象 14 TABLESPACE对象设计 规则2.8 禁止自定义TABLESPACE表空间 15 TABLE对象设计(重点) 规则2.9 创建表时必须选择正确的分布方式和分布列 16 规则2.10 创建表时必须选择正确的存储方式 17 规则2.11 创建表时必须选择正确的分区策略 18 建议2.12 表字段的设计要遵循高效、准确原则 19 建议2.13 避免使用自增列或自增数据类型 20 INDEX对象设计(重点) 规则2.14 只创建必要的索引,创建索引必须选择合适的列和顺序 21 建议2.15 列存表通常可不建索引,极致性能场景需正确选择索引类型 22 VIEW对象设计 建议2.16 视图的嵌套需避免超过三层 23 SQL开发规范 DDL操作规范 建议3.1 DDL操作(CREATE除外)避免在业务高峰期和长事务中执行 24 规则3.2 DROP删除对象操作必须明确删除对象范围 25 INSERT操作规范 规则3.3 INSERT多VALUES批插场景使用COPY替代 26 建议3.4 禁止针对普通列存表进行实时INSERT操作 27 UPDATE/DELETE操作规范 建议3.5 避免并发UPDATE/DELETE行存表的同一行 28 建议3.6 避免对列存表频繁或并发执行UPDATE/DELETE 29 SELECT操作规范 规则3.7 禁止执行不下推的SQL 30 规则3.8 禁止多表关联时缺少关联条件 31 规则3.9 多表关联字段数据类型要保持一致 32 建议3.10 尽量避免对关联条件字段和过滤条件字段进行函数运算 33 建议3.11 资源高消耗型SQL需做好压测和并发管控 34 规则3.12 禁止针对行存大表的频繁COUNT 35 建议3.13 避免查询返回超大结果集(数据导出场景除外) 36 建议3.14 查询时避免使用“SELECT *”写法 37 建议3.15 谨慎使用递归语句(WITH RECURSIVE),明确终止条件,确保递归可终止 38 建议3.16 访问对象(表,函数等)时带上SCHEMA名称 39 建议3.17 针对SQL标记注释,唯一标识SQL的归属 40 存储过程开发规范 - 建议4.1 避免使用复杂的存储过程,避免存储过程嵌套 41 规则4.2 存储过程内需避免执行非CREATE类的DDL操作
  • 规则2.11 创建表时必须选择正确的分区策略 违反规范的影响: 分区的优点如下,如不做分区,其查询性能和 数据治理 效率会下降,数据量越大这种劣化越大。 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索效率。 提升数据治理效率:如数据生命周期管理场景,针对历史分区做TRUNCATE/DROP PARTITION,效率和效果远优于DELETE。 方案建议: 针对包含时间类型字段的表设计分区。 表3 分区策略选择 分区策略 描述 适用场景 范围分区(Range Partitioning) 根据分区键值的范围,将数据存储到不同的分区中,分区键范围连续但不重叠。 日期或者时间类的字段作为分区键。 查询中大多包含分区键作为过滤条件。 定期按照分区键清理数据。 列表分区(List Partitioning) 根据分区键值的列表进行分区,各分区的列表值不重复 特定数量的枚举值作为分区键值。 查询中大多包含分区键作为过滤条件。
  • 规则2.10 创建表时必须选择正确的存储方式 违反规范的影响: 行存表使用不当导致查询场景性能差,资源过载。 列存表使用不当导致CU膨胀,性能差,资源过载。 方案建议: 创建表时通过orientation显式指定表的存储类型,存储类型的选择原则如下表所示。 表2 存储类型选择 存储方式 适用场景 不适用的场景 行存 DML增删改:UPDATE和DELETE操作多的场景 DML查询:点查询(返回记录少,基于索引的简单查询) DML查询:统计分析类查询 (group , join的数据量大的场景)。 注意: 创建行存表(orientation = row)时,禁止指定compress属性,禁止使用行存压缩表。 列存 DML增删改:INSERT批量导入场景(单次单分区入库量接近或大于6w*DN数) DML查询:统计分析类查询 (group , join的数据量大的场景) DML增删改:UPDATE/DELETE多的场景、INSERT小批量插入的场景。 DML查询:高并发的点查询。
  • 建议2.12 表字段的设计要遵循高效、准确原则 违反规范的影响: 存储空间大、查询效率降低。 方案建议: 选择最高效的类型。 如能整型就不用浮点型,能用整型就不用字符型。 使用变长字符类型时根据数据特征指定最大长度。 选择最准确的类型。 使用时间类型存储时间,不使用字符类型存储时间。 使用满足需求的最小数值类型,如果int或smallint够用,就不用bigint而浪费空间。 正确使用约束。 明确不存在NULL值的字段加上NOT NULL约束,优化器会在特定场景下对其进行自动优化。 业务层面能补全的字段,不要使用DEFAULT约束,避免数据加载时产生不符合预期的结果。 避免非必要类型转换。 当多个表存在逻辑关系时,表示同一含义的字段应该使用相同的数据类型。 不同类型的比较操作会导致数据类型转换,可能导致索引和分区剪枝失效,影响查询性能。
  • 规则2.9 创建表时必须选择正确的分布方式和分布列 违反规范的影响: 分布式和分布列选择错误,导致表数据存储倾斜,访问性能下降,严重情况会触发存储和计算资源过载。 方案建议: 创建表时通过DISTRIBUT BY显式指定分布方式和分布列,分布列选择原则如下表所示。 表1 分布列选择原则 分布方式 描述 适用场景 Hash 表数据按照分布列生成的hash值与DN实例的映射关系,将数据分布到各DN实例。 优点:每个DN仅包含部分数据,占用整体空间小。 缺点:数据分布的均匀程度强依赖分布列的选择;JOIN关联条件不包含各自分布列的场景存在节点间数据通信的消耗。 大表、事实表。 RoundRobin 表数据按照轮询的方式依次分布到各DN实例。 优点:每个DN仅包含部分数据,占用整体空间小;数据轮询均匀分布,不依赖分布列,不存在数据存储倾斜问题。 缺点:无法通过分布列条件消除和减少节点间通信,此类场景性能不如HASH。 大表、事实表,无合适分布列的表。 Replication 表中的全量数据在集群的每一个DN实例上保留一份。 优点:每个DN上都有此表的全量数据,JOIN操作中可以完全避免节点间数据通信,从而减小网络开销,同时减少了STREAM线程启停开销。 缺点:每个DN都保留了表的完整数据,数据的冗余,占用更多存储空间。 小表、维度表。
  • 空间索引 GaussDB(DWS)数据库的PostGIS Extension支持GIST (Generalized Search Tree) 空间索引(分区表除外)。相比于B-tree索引,GIST索引适应于任意类型的非常规数据结构,可有效提高几何和地理数据信息的检索效率。 使用如下命令创建GIST索引: 1 CREATE INDEX indexname ON tablename USING GIST ( geometryfield );
  • 建议3.4 禁止针对普通列存表进行实时INSERT操作 违反规范的影响: 针对普通列存表实时小批量入库会导致小CU膨胀严重,影响存储空间和查询性能。 方案建议: 实时INSERT场景评估单次入库数据量和数据总量,总量小的场景可以改为行存表。 实时INSERT场景前端攒批,保证单次、单表、单分区、单DN入库数据量接近6W,建议最低不少于5K。 实时INSERT场景使用Hstore列存表(8.3.0及以上版本)。
  • 规则2.14 只创建必要的索引,创建索引必须选择合适的列和顺序 违反规范的影响: 冗余索引浪费空间,索引多影响入库效率。 组合索引中列顺序错误,影响查询效率。 最佳实践: 索引的使用需兼顾以下条件: 索引列必须是常用于过滤条件或JOIN关联条件的列。 索引列必须是DISTINCT值多的列。 创建多列组合索引时,DISTINCT值多的列往前放。 单表索引个数控制在5个以内,可通过组合索引控制索引的个数。 数据批量增删改场景,建议先删除索引,完成增删改后再加回索引,提升批量操作性能(实时访问会有影响)。
  • SQLSetEnvAttr 功能描述 设置控制环境各方面的属性。 原型 1 2 3 4 SQLRETURN SQLSetEnvAttr(SQLHENV EnvironmentHandle SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength); 参数 表16 SQLSetEnvAttr参数 关键字 参数说明 EnvironmentHandle 环境句柄。 Attribute 需设置的环境属性,可为如下值: SQL_ATTR_ODBC_VERSION:指定ODBC版本。 SQL_CONNECTION_POOLING:连接池属性。 SQL_OUTPUT_NTS:指明驱动器返回字符串的形式。 ValuePtr 指向对应Attribute的值。依赖于Attribute的值,ValuePtr可能是32位整型值,或为以空结束的字符串。 StringLength 如果ValuePtr指向字符串或二进制缓冲区,这个参数是*ValuePtr长度,如果ValuePtr指向整型,忽略StringLength。 返回值 SQL_SUC CES S:表示调用正确。 SQL_SUCCESS_WITH_INFO:表示会有一些警告信息。 SQL_ERROR:表示比较严重的错误,如:内存分配失败、建立连接失败等。 SQL_INVALID_HANDLE:表示调用无效句柄。其他API的返回值同理。 注意事项 当SQLSetEnvAttr的返回值为SQL_ERROR或SQL_SUCCESS_WITH_INFO时,通过借助SQL_HANDLE_ENV的HandleType和EnvironmentHandle的Handle,调用SQLGetDiagRec可得到相关的SQLSTATE值,通过SQLSTATE值可以查出调用此函数的具体信息。 示例 参见:示例
  • SQLSetStmtAttr 功能描述 设置相关语句的属性。 原型 1 2 3 4 SQLRETURN SQLSetStmtAttr(SQLHSTMT StatementHandle SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength); 参数 表17 SQLSetStmtAttr参数 关键字 参数说明 StatementtHandle 语句句柄。 Attribute 需设置的属性。 ValuePtr 指向对应Attribute的值。依赖于Attribute的值,ValuePtr可能是32位无符号整型值,或指向以空结束的字符串,二进制缓冲区,或者驱动定义值。注意,如果ValuePtr参数是驱动程序指定值。ValuePtr可能是有符号的整数。 StringLength 如果ValuePtr指向字符串或二进制缓冲区,这个参数是*ValuePtr长度,如果ValuePtr指向整型,忽略StringLength。 返回值 SQL_SUCCESS:表示调用正确。 SQL_SUCCESS_WITH_INFO:表示会有一些警告信息。 SQL_ERROR:表示比较严重的错误,如:内存分配失败、建立连接失败等。 SQL_INVALID_HANDLE:表示调用无效句柄。其他API的返回值同理。 注意事项 当SQLSetStmtAttr的返回值为SQL_ERROR或SQL_SUCCESS_WITH_INFO时,通过借助SQL_HANDLE_STMT的HandleType和StatementHandle的Handle,调用SQLGetDiagRec可得到相关的SQLSTATE值,通过SQLSTATE值可以查出调用此函数的具体信息。 示例 参见:示例