云服务器内容精选

  • 建议4.1 避免使用复杂的存储过程,避免存储过程嵌套 违反规范的影响: 复杂和嵌套的存储过程维护成本高,故障定位难度大,恢复耗时长。 方案建议: 不使用存储过程或只使用一层存储过程,不嵌套。 开发存储过程设计对应的日志表,将关键步骤前后的信息记录到日志表中,操作步骤如下。 保存并查看日志操作步骤 创建日志表。 1 2 3 4 5 6 7 8 9 CREATE TABLE func_exec_log ( id varchar2(32) default lower(sys_guid()), pro_name varchar2(60), exec_times int, log_date date, deal_date date, log_mesage text ); 创建表和导入数据。 1 2 CREATE TABLE demo_table(data_id int, data_number int); INSERT INTO demo_table values(generate_series(1,1000),generate_series(1,1000)); 创建业务存储过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 CREATE OR REPLACE FUNCTION demo_table_process(out exe_info text) LANGUAGE plpgsql AS $$ declare v_count int; pro_result text; fun_name text; exec_times int; begin fun_name := 'demo_table_process'; select nvl(max(exec_times), '0') + 1 into exec_times from func_exec_log where pro_name = fun_name; --业务表插入数据 insert into demo_table values (dbms_random.value(1, 1000)::int,generate_series(1, dbms_random.value(10000, 20000)::int)); get diagnostics v_count = ROW_COUNT; exe_info = sysdate || '# step1:insert count:' || v_count || ' rows;'; --删除业务表指定数据 delete from demo_table where data_id = dbms_random.value(1, 1000)::int; get diagnostics v_count = ROW_COUNT; exe_info = exe_info || sysdate || '# step2:delete count:' || v_count || ' rows;'; --更新业务表数据 update demo_table set data_number = dbms_random.value(1, 100)::int where data_id = dbms_random.value(1, 1000)::int; exe_info = exe_info || sysdate || '# step3:update count:' || sql%rowcount || ' rows'; --在整个程序结束前记录日志,也可以在每个步骤结束后分别记录日志,也可以创建记录日志的函数供调用,灵活使用即可 insert into func_exec_log(pro_name, exec_times, log_date, deal_date, log_mesage) values (fun_name,exec_times,sysdate,split_part(regexp_split_to_table(exe_info, ';'), '#', 1),split_part(regexp_split_to_table(exe_info, ';'), '#', 2)); --EXCEPTION用于保证当insert/update/delete等操作步骤异常退出时,也能够正常记录日志 EXCEPTION WHEN OTHERS THEN pro_result := exe_info || sysdate || '# exception error message is: ' || sqlerrm; insert into func_exec_log(pro_name, exec_times, log_date, deal_date, log_mesage) values(fun_name,exec_times,sysdate,split_part(regexp_split_to_table(pro_result, ';'), '#', 1),split_part(regexp_split_to_table(pro_result, ';'), '#', 2)); END; $$; 调用存储过程(正常执行)。 1 SELECT demo_table_process(); 查看日志(确认业务运行情况)。 SELECT * FROM func_exec_log ORDER BY log_date desc,deal_date,log_mesage; 再次调用存储过程(构造执行异常)。 SELECT demo_table_process(); --先删除demo_table的data_number列构造异常,之后再调用 查看日志(确认业务运行情况)。
  • 释放连接 【建议】推荐使用连接池限制应用程序的连接数。每执行一条SQL就连接一次数据库,是一种不好SQL的编写习惯。 【建议】在应用程序完成作业任务之后,应当及时断开和 GaussDB (DWS)的连接,释放资源。建议在任务中设置session超时时间参数。 【建议】使用JDBC连接池,在将连接释放给连接池前,需要执行以下操作重置会话环境。否则,可能会因为历史会话信息导致的对象冲突。 如果在连接中设置了GUC参数,那么在将连接归还连接池之前,必须执行“SET SESSION AUTHORIZATION DEFAULT;RESET ALL;”将连接的状态清空。 如果使用了临时表,那么在将连接归还连接池之前,必须将临时表删除。
  • 连接参数 【关注】第三方工具通过JDBC连接GaussDB(DWS)时,JDBC向GaussDB(DWS)发起连接请求,会默认添加以下配置参数,详见JDBC代码ConnectionFactoryImpl类的实现。 params = { { "user", user }, { "database", database }, { "client_encoding", "UTF8" }, { "DateStyle", "ISO" }, { "extra_float_digits", "2" }, { "TimeZone", createPostgresTimeZone() }, }; 这些参数可能会导致JDBC客户端的行为与gsql客户端的行为不一致,例如,Date数据显示方式、浮点数精度表示、timezone显示。 如果实际期望和这些配置不符,建议在java连接设置代码中显式设定这些参数。 【建议】通过JDBC连接数据库时,应该保证下面两个时区设置一致: JDBC客户端所在主机的时区。 GaussDB(DWS)集群所在主机的时区。
  • 数据加载和卸载 【建议】在insert语句中显式给出插入的字段列表。例如: 1 INSERT INTO task(name,id,comment) VALUES ('task1','100','第100个任务'); 【建议】在批量数据入库之后,或者数据增量达到一定阈值后,建议对表进行analyze操作,防止统计信息不准确而导致的执行计划劣化。 【建议】如果要清理表中的所有数据,建议使用truncate table方式,不要使用delete table方式。delete table方式删除性能差,且不会释放那些已经删除了的数据占用的磁盘空间。
  • DDL 【建议】在GaussDB(DWS)中,建议DDL(建表、comments等)操作统一执行,在批处理作业中尽量避免DDL操作。避免大量并发事务对性能的影响。 【建议】在非日志表(unlogged table)使用完后,立即执行数据清理(truncate)操作。因为在异常场景下,GaussDB(DWS)不保证非日志表(unlogged table)数据的安全性。 【建议】临时表和非日志表的存储方式建议和基表相同。当基表为行存(列存)表时,临时表和非日志表也推荐创建为行存(列存)表,可以避免行列混合关联带来的高计算代价。 【建议】索引字段的总长度不超过50字节。否则,索引大小会膨胀比较严重,带来较大的存储开销,同时索引性能也会下降。 【建议】不要使用DROP…CASCADE方式删除对象,除非已经明确对象间的依赖关系,以免误删。
  • 总体开发原则 应完全按照设计文档进行开发。 程序模块应做到高内聚低耦合。 应有正确、全面的故障对策。 程序编写应做到结构合理,条理清晰。 程序名称命名应按照统一的命名规则进行命名。 应充分考虑程序的运行效率,包括程序的执行效率和数据库的查询、存储效率,在保证应用的同时应使用效率高的处理方法。 程序注释应详细、正确、规范。 除非应用特别需要控制commit和rollback的提交时机,否则应在存储过程结束时执行显式的commit或者rollback操作。 程序处理应支持7*24小时;对于中断,应用程序应提供安全、简单的断点再续处理。 应提供标准、简单的应用输出,为应用维护人员提供明确的进度显示、错误描述和运行结果;为业务人员提供明确、直观的报表、凭证输出。
  • 程序编写原则 在PL/PGSQL中的SQL语句宜使用绑定变量。 在PL/PGSQL中的SQl语句宜使用RETURNING字句。 存储过程使用原则: 对于单个存储过程中Varchar或者Varchar2类型输出参数个数不应超过50个。 不应使用long类型作为输入或输出参数。 对于大小超过10MB的字符串类型输出,应使用CLOB类型。 变量声明原则: 变量声明时,如果含义和应用表某字段含义或某变量相同时,应使用%TYPE声明。 记录声明时,如果含义和某应用表行数据相同时,应使用%ROWTYPE声明。 变量声明每行应只包含一条语句。 不应声明LONG类型的变量。 游标使用类型: 显式游标使用后应关闭。 游标变量使用后应关闭,若游标变量需要传递数据给调用的应用程序,应在应用程序中进行游标关闭处理;若游标变量仅在存储过程中使用,应显式关闭游标。 在使用DBMS_SQL.CLOSE_CURSOR关闭游标前,应使用DBMS_SQL.IS_OPEN判断游标是否已打开。 集合使用原则: 引用集合中的元素时宜使用FORALL语句,不宜使用FOR循环语句。 动态语句使用原则: 联机系统的交易程序不宜使用动态SQL。 PL/PGSQL中要实现DDL语句和系统控制命令,可使用动态SQL。 宜尽量使用变量绑定。 拼装SQL的使用原则: 拼装SQL宜使用绑定变量。 拼装SQL语句的条件如果有外部输入源,应对输入条件进行字符检查,防止攻击。 在PL/PGSQL脚本中,单行代码的长度,不宜超过2499字符。 Trigger使用原则: Trigger可用于实现差量数据日志等于业务处理无关的可用性设计场景。 不应使用Trigger实现业务处理相关功能。
  • 书写规范 变量命名规则: 过程、函数的输入参数格式宜为:IN_参数名,参数名宜使用大写。 过程、函数的输出参数格式宜为:OUT_参数名,参数名宜使用大写。 过程、函数得输入输出参数格式宜为:IO_参数名,参数名宜使用大写。 过程、函数得程序中用到的变量宜由v_变量名组成,变量名宜使用小写。 将查询语句做成字符串拼接时,where语句的拼接变量名宜统一为v_where,select语句的拼接变量名宜为v_select。 记录(RECORD)的类型(TYPE)命名宜由T+变量名组成,名称宜使用大写。 游标命名宜由CUR+变量名组成,名称宜使用大写。 引用游标(REF CURSOR)的命名宜由REF+变量名组成,名称宜使用大写。 变量类型定义: 变量类型声明时,如果其含义和应用表某字段含义相同时,应使用%TYPE声明。 记录类型声明时,如果其含义和某应用表行数据相同时,应使用%ROWTYPE声明。 注释规范: 注释应该是有意义的,而不应是重述代码。 注释应简洁、易懂,以中文为主。为了表达准确,名词或操作上也可以使用英文。 应在每个存储过程、函数得开始加入注释,内容应包括:本程序的简要功能描述、编写者、编写日期、程序版本号信息和程序变更信息,而且各存储过程开头注释应保持统一格式。 应在输入输出参数的旁边添加注释,注明次变量的意义。 每个块或大分支的开始宜添加注释,描述块的简要功能,若使用算法,宜添加注释简单描述算法的目的和结果。 变量声明格式: 每行应只包含一条语句,如同时需要赋初始值,应在同一行书写。 大小写规范: 除了变量名,应一律使用大写。 缩进规范: 创建存储过程语句中,同一层的CREATE、AS/IS、BEGIN、END这几个关键字应位于同一列,其他部分依次缩进。 语句详述: 变量定义语句。每行应只包含一条语句。 同一层的IF、ELSEIF、ELSE和END关键字应开始于同一列,执行语句缩进。 CASE和END关键字应位于同一列,WHEN和ELSE关键字应缩进。 同一层的LOOP和END LOOP关键字应位于同一列,层内语句或嵌套应依次缩进。
  • 异常处理原则 任何在PL/pgSQL函数中发生的错误会中止该函数的执行,而且实际上会中止其周围的事务。你可以使用一个带有EXCEPTION子句的BEGIN块俘获错误并且从中恢复。 在使用PL/PGSQL块中,如果使用了不能返回确定结果的SQL语句,宜在EXCEPTION中对程序可能出现的异常进行处理,避免出现未处理的出错被传递到外层块,导致程序逻辑错误。 对于系统已经定义了的异常,可以直接使用。DWS暂不支持自定义异常。 进入和退出一个包含EXCEPTION子句的块要比不包含的块开销大的多。因此,非必要场景不应使用EXCEPTION。