华为云用户手册

  • 示例 创建示例表和索引: create table t1(c1 int, c2 int, c3 int); create table t2(c1 int, c2 int, c3 int); create table t3(c1 int, c2 int, c3 int); create index it1 on t1(c1,c2); create index it2 on t2(c1,c2); create index it3 on t1(c3,c2); -- 下面TPCH数据表需要插入10X数据量已匹配给出的计划示例 create table store ( s_store_sk integer not null, s_store_id char(16) not null, s_rec_start_date date , s_rec_end_date date , s_closed_date_sk integer , s_store_name varchar(50) , s_number_employees integer , s_floor_space integer , s_hours char(20) , s_manager varchar(40) , s_market_id integer , s_geography_class varchar(100) , s_market_desc varchar(100) , s_market_manager varchar(40) , s_division_id integer , s_division_name varchar(50) , s_company_id integer , s_company_name varchar(50) , s_street_number varchar(10) , s_street_name varchar(60) , s_street_type char(15) , s_suite_number char(10) , s_city varchar(60) , s_county varchar(30) , s_state char(2) , s_zip char(10) , s_country varchar(20) , s_gmt_offset decimal(5,2) , s_tax_precentage decimal(5,2) , primary key (s_store_sk) ); create table store_sales ( ss_sold_date_sk integer , ss_sold_time_sk integer , ss_item_sk integer not null, ss_customer_sk integer , ss_cdemo_sk integer , ss_hdemo_sk integer , ss_addr_sk integer , ss_store_sk integer , ss_promo_sk integer , ss_ticket_number integer not null, ss_quantity integer , ss_wholesale_cost decimal(7,2) , ss_list_price decimal(7,2) , ss_sales_price decimal(7,2) , ss_ext_discount_amt decimal(7,2) , ss_ext_sales_price decimal(7,2) , ss_ext_wholesale_cost decimal(7,2) , ss_ext_list_price decimal(7,2) , ss_ext_tax decimal(7,2) , ss_coupon_amt decimal(7,2) , ss_net_paid decimal(7,2) , ss_net_paid_inc_tax decimal(7,2) , ss_net_profit decimal(7,2) , primary key (ss_item_sk, ss_ticket_number) ); create table store_returns ( sr_returned_date_sk integer , sr_return_time_sk integer , sr_item_sk integer not null, sr_customer_sk integer , sr_cdemo_sk integer , sr_hdemo_sk integer , sr_addr_sk integer , sr_store_sk integer , sr_reason_sk integer , sr_ticket_number integer not null, sr_return_quantity integer , sr_return_amt decimal(7,2) , sr_return_tax decimal(7,2) , sr_return_amt_inc_tax decimal(7,2) , sr_fee decimal(7,2) , sr_return_ship_cost decimal(7,2) , sr_refunded_cash decimal(7,2) , sr_reversed_charge decimal(7,2) , sr_store_credit decimal(7,2) , sr_net_loss decimal(7,2) , primary key (sr_item_sk, sr_ticket_number) ); create table customer ( c_customer_sk integer not null, c_customer_id char(16) not null, c_current_cdemo_sk integer , c_current_hdemo_sk integer , c_current_addr_sk integer , c_first_shipto_date_sk integer , c_first_sales_date_sk integer , c_salutation char(10) , c_first_name char(20) , c_last_name char(30) , c_preferred_cust_flag char(1) , c_birth_day integer , c_birth_month integer , c_birth_year integer , c_birth_country varchar(20) , c_login char(13) , c_email_address char(50) , c_last_review_date char(10) , primary key (c_customer_sk) ); create table promotion ( p_promo_sk integer not null, p_promo_id char(16) not null, p_start_date_sk integer , p_end_date_sk integer , p_item_sk integer , p_cost decimal(15,2) , p_response_target integer , p_promo_name char(50) , p_channel_dmail char(1) , p_channel_email char(1) , p_channel_catalog char(1) , p_channel_tv char(1) , p_channel_radio char(1) , p_channel_press char(1) , p_channel_event char(1) , p_channel_demo char(1) , p_channel_details varchar(100) , p_purpose char(15) , p_discount_active char(1) , primary key (p_promo_sk) ); create table customer_address ( ca_address_sk integer not null, ca_address_id char(16) not null, ca_street_number char(10) , ca_street_name varchar(60) , ca_street_type char(15) , ca_suite_number char(10) , ca_city varchar(60) , ca_county varchar(30) , ca_state char(2) , ca_zip char(10) , ca_country varchar(20) , ca_gmt_offset decimal(5,2) , ca_location_type char(20) , primary key (ca_address_sk) ); create table item ( i_item_sk integer not null, i_item_id char(16) not null, i_rec_start_date date , i_rec_end_date date , i_item_desc varchar(200) , i_current_price decimal(7,2) , i_wholesale_cost decimal(7,2) , i_brand_id integer , i_brand char(50) , i_class_id integer , i_class char(50) , i_category_id integer , i_category char(50) , i_manufact_id integer , i_manufact char(50) , i_size char(20) , i_formulation char(20) , i_color char(20) , i_units char(10) , i_container char(10) , i_manager_id integer , i_product_name char(50) , primary key (i_item_sk) ); 本章节大部分示例使用下述语句,便于Plan Hint支持的各方法作对比,示例语句及不带hint的原计划如下所示:
  • 告警场景 目前支持对以下7种导致性能问题的场景上报告警。 多列/单列统计信息未收集 如果存在单列或者多列统计信息未收集,则上报相关告警。 告警信息示例: 整表的统计信息未收集: 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表达式,会告警相应语法不支持下推等。 告警信息示例: 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,且连接的内表行数是外表行数的10倍或以上,同时内表在每个DN上的平均行数大于10万行,且发生了下盘,则上报相关告警。调优方法请参见使用plan hint调优执行计划。 大表等值连接使用Nestloop 如果在表连接过程中使用了nestloop,并且两个表中较大表的行数平均每个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等其他算子很可能也出现数据倾斜。
  • 使用分区表 分区表是把逻辑上的一张表根据某种方案分成几张物理块进行存储。这张逻辑上的表称之为分区表,物理块称之为分区。分区表是一张逻辑表,不存储数据,数据实际是存储在分区上的。分区表和普通表相比具有以下优点: 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索效率。 增强可用性:如果分区表的某个分区出现故障,表在其他分区的数据仍然可用。 方便维护:如果分区表的某个分区出现故障,需要修复数据,只修复该分区即可。 GaussDB 支持的分区表为范围分区表、列表分区表和哈希分区表。 范围分区表:将数据基于范围映射到每一个分区。这个范围是由创建分区表时指定的分区键决定的。分区键经常采用日期,例如将销售数据按照月份进行分区。 列表分区表:将数据中包含的键值分别存储在不同的分区中,依次将数据映射到每一个分区,分区中包含的键值由创建分区表时指定。 哈希分区表:将数据根据内部哈希算法依次映射到每一个分区中,包含的分区个数由创建分区表时指定。 父主题: 审视和修改表定义
  • 操作步骤 收集SQL中涉及到的所有表的统计信息。在数据库中,统计信息是优化器生成计划的源数据。没有收集统计信息或者统计信息陈旧往往会造成执行计划严重劣化,从而导致性能问题。从经验数据来看,10%左右性能问题是因为没有收集统计信息。具体请参见更新统计信息。 通过查看执行计划来查找原因。如果SQL长时间运行未结束,通过EXPLAIN命令查看执行计划,进行初步定位。如果SQL可以运行出结果,则推荐使用EXPLAIN ANALYZE或EXPLAIN PERFORMANCE查看执行计划及实际运行情况,以便更精确地定位问题原因。有关执行计划的详细介绍请参见SQL执行计划介绍。 审视和修改表定义。 针对EXPLAIN或EXPLAIN PERFORMANCE信息,定位SQL慢的具体原因以及改进措施,具体请参见典型SQL调优点。 通常情况下,有些SQL语句可以通过查询重写转换成等价的,或特定场景下等价的语句。重写后的语句比原语句更简单,且可以简化某些执行步骤达到提升性能的目的。查询重写方法在各个数据库中基本是通用的。经验总结:SQL语句改写规则介绍了几种常用的通过改写SQL进行调优的方法。
  • 执行计划显示信息 除了设置不同的执行计划显示格式外,还可以通过不同的EXPLAIN用法,显示不同详细程度的执行计划信息。常见有如下几种,关于更多用法请参见EXPLAIN语法说明。 EXPLAIN statement:只生成执行计划,不实际执行。其中statement代表SQL语句。 EXPLAIN ANALYZE statement:生成执行计划,进行执行,并显示执行的概要信息。显示中加入了实际的运行时间统计,包括在每个规划节点内部花费的总时间(以毫秒计)和它实际返回的行数。 EXPLAIN PERFORMANCE statement:生成执行计划,进行执行,并显示执行期间的全部信息。 为了测量运行时在执行计划中每个节点的开销,EXPLAIN ANALYZE或EXPLAIN PERFORMANCE会在当前查询执行上增加性能分析的开销。在一个查询上运行EXPLAIN ANALYZE或EXPLAIN PERFORMANCE有时会比普通查询明显的花费更多的时间。超出的时间多少取决于查询本身复杂程度和使用的平台。 因此,当定位SQL运行慢问题时,如果SQL长时间运行未结束,建议通过EXPLAIN命令查看执行计划,进行初步定位。如果SQL可以运行出结果,则推荐使用EXPLAIN ANALYZE或EXPLAIN PERFORMANCE查看执行计划及其实际的运行信息,以便更精确地定位问题原因。
  • 调优手段之GUC参数 查询优化的主要目的是为查询语句选择高效的执行方式。 如下SQL语句: 1 2 select count(1) from customer inner join store_sales on (ss_customer_sk = c_customer_sk); 在执行customer inner join store_sales的时候,GaussDB支持Nested Loop、Merge Join和Hash Join三种不同的Join方式。优化器会根据表customer和表store_sales的统计信息估算结果集的大小以及每种Join方式的执行代价,然后对比选出执行代价最小的执行计划。 正如前面所说,执行代价计算都是基于一定的模型和统计信息进行估算,当因为某些原因代价估算不能反映真实的cost的时候,就需要通过GUC参数设置的方式让执行计划倾向更优规划。例如:random_page_cost参数表示优化器计算一次非顺序抓取磁盘页面的开销,该参数默认值为4。当机器磁盘随机读取的速度较快时,比如SSD设备,可以将该参数的值适当调小,更改后,索引扫描的代价降低,生成计划时更倾向于选择索引扫描的方式。
  • JDBC兼容性包 从发布包中获取。包名为GaussDB-Kernel_数据库版本号_操作系统版本号_64bit_Jdbc.tar.gz。 解压后JDBC的驱动jar包: gsjdbc4.jar:主类名为“org.postgresql.Driver”,数据库连接的URL前缀为“jdbc:postgresql”,该驱动包适用于从PostgreSQL迁移业务的场景,驱动类和加载路径与迁移前保持一致,但接口支持情况不完全一致,未支持的接口需要业务侧进行调整。 gsjdbc200.jar:该驱动包适用于从Gauss200迁移业务的场景,驱动类和加载路径与迁移前保持一致,但接口支持情况不完全一致,未支持的接口需要业务侧进行调整。 opengaussjdbc.jar:主类名为“com.huawei.opengauss.jdbc.Driver”,数据库连接的URL前缀为“jdbc:opengauss”。如果遇到同一JVM进程内需要同时访问PostgreSQL及GaussDB的场景,请使用此驱动包。 各驱动包只是驱动类加载路径和url前缀不同,接口功能相同。 不能使用gsjdbc4的驱动包操作PostgreSQL数据库,虽然部分版本能够建连成功,但部分接口行为与PostgreSQL JDBC不同,可能导致未知错误 不能使用PostgreSQL的驱动包操作 GaussDB数据库 ,虽然部分版本能够建连成功,但部分接口行为与GaussDB JDBC不同,可能导致未知错误。
  • ecpg兼容 ecpg提供使用URL连接方式的连接语法,不仅支持“gaussdb”,还兼容支持“postgresql”。 连接语法: EXEC SQL CONNECT TO target [AS connection-name] [USER user-name]; 其中target支持“postgresql”方式如下: tcp:postgresql://hostname[:port][/dbname][?options] unix:postgresql://hostname[:port][/dbname][?options]
  • type ColumnType type ColumnType如下表所示。 方法 描述 返回值 (ci *ColumnType)DatabaseTypeName() 返回列类型的数据库系统名称。返回空字符串表示该驱动类型名字并未被支持。 error (ci *ColumnType)DecimalSize() 返回小数类型的范围和精度。 返回值ok的值为false时,说明给定的类型不可用或者不支持。 precision, scale int64, ok boolean (ci *ColumnType)Length() 返回数据列类型长度。返回值ok的值为false时,说明给定的类型不存在长度。 length int64, ok boolean (ci *ColumnType)ScanType() 返回一种Go类型,该类型能够在Rows.scan进行扫描时使用。 reflect.Type (ci *ColumnType)Name() 返回数据列的名字。 string 父主题: Go接口参考
  • 参数说明 参数 参数说明 ctx 表示给定的上下文。 query 被执行的sql语句。 args 被执行sql语句需要绑定的参数。支持按位置绑定和按名称绑定,详情见如下示例。 opts 事务隔离级别和事务访问模式,其中事务隔离级别(opts.Isolation)支持范围为sql.LevelReadUncommitted、sql.LevelReadCommitted、sql.LevelRepeatableRead、sql.LevelSerializable。事务访问模式(opts.ReadOnly)支持范围为true(read only)和false(read write)。 Query类接口Query()、QueryContext()、QueryRow()、QueryRowContext()通常用于查询语句,如SELECT语句。操作语句使用Exec()接口执行,若非查询语句通过Query类接口执行,则执行结果可能与预期不符,因此不建议使用Query类接口执行非查询语句,例如UPDATE/INSERT等。 使用Query类接口执行查询语句的结果需要通过type Rows中Next()接口获取,若不通过Next()接口获取,可能会产生不可预期的错误。
  • 示例 //本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置) package main /* go驱动依赖包位置根据配置的go.mod设置 */ import ( "database/sql" _ "gitee.com/opengauss/openGauss-connector-go-pq" "log" ) func main() { hostip := os.Getenv("GOHOSTIP") //GOHOSTIP为写入环境变量的IP地址 port := os.Getenv("GOPORT") //GOPORT为写入环境变量的port usrname := os.Getenv("GOUSRNAME") //GOUSRNAME为写入环境变量的用户名 passwd := os.Getenv("GOPASSWD") //GOPASSWDW为写入环境变量的用户密码 str := "host=" + hostip + " port=" + port + " user=" + usrname + " password=" + passwd + " dbname=gaussdb sslmode=disable" db, err := sql.Open("gaussdb", str) if err != nil { log.Fatal(err) } defer db.Close() err = db.Ping() if err != nil { log.Fatal(err) } _, err = db.Exec("create table test_bound(id int, name text)") // 按位置绑定 _, err = db.Exec("insert into test_bound(id, name) values(:1, :2)", 1, "张三") if err != nil { log.Fatal(err) } // 按名称绑定 _, err = db.Exec("insert into test_bound(id, name) values(:id, :name)", sql.Named("id", 1), sql.Named("name", "张三")) if err != nil { log.Fatal(err) } }
  • 环境类 Go环境配置 用户需要在环境变量中配置以下参数: GO111MODULE:用户使用在线导入的方式安装Go驱动时需要设置GO111MODULE为on。如果不希望进行go mod工程的改造,需将GO111MODULE设置为off,并手动下载依赖包。依赖包与驱动根目录和业务代码保持同级。 GOPROXY:用户使用在线导入时需配置包含Go驱动包的路径。 用户可以根据自己场景参数配置Go其他相关环境变量。 通过go env查看Go环境变量配置结果,并且查看Go版本是否在1.13或以上。 Go驱动安装 从发布包中获取Go驱动包。包名为GaussDB -Kernel_数据库版本号_操作系统版本号_64bit_Go.tar.gz。解压后为Go驱动源码包。 进入Go驱动代码根路径,执行go mod tidy下载相关依赖,需要在环境变量中配置GOPATH=${Go驱动依赖包存放路径}。 若依赖已下载至本地,可以在go.mod里面添加一行“通过replace将Go驱动包替换为本地Go驱动包地址”,表示代码里面所有的import Go驱动包都是使用本地路径,同时依赖也不会从代理里下载。 通过go mod tidy下载相关依赖时可能会下载为某个依赖的低版本,如果依赖的低版本存在漏洞,可以通过更改go.mod文件中对应依赖的版本号,更新依赖到漏洞修复后的版本来规避风险。 用户不涉及驱动开发,调用需go 1.13版本或以上即可,runtime运行库需要更新至1.18版本及以上。
  • ecpg与Pro*C兼容性对比 ecpg是GaussDB提供的一种用于C语言程序的嵌入式SQL预处理器,与ORA数据库Pro*C预处理器在编译执行命令、语法、嵌入式语句等行为和语义上存在差异。 ecpg与Pro*C的相关使用差异对比: 目前ecpg不支持EXEC SQL CONTEXT ALLOCATE、EXEC SQL CONTEXT USE、EXEC SQL CONTEXT FREE。 ecpg当前不支持CONTEXT申请、使用、释放操作,ecpg有独立的内存管理机制。多线程模式下,ecpg在每个线程中独立地建立连接、执行SQL语句以及相关资源的释放。这一使用方式与Pro*C多线程程模式下每个线程各自进行CONTEXT相关申请与释放的处理逻辑一致。 目前ecpg不支持EXEC SQL COMMIT WORK RELEASE。 在ecpg中,当业务语句执行COMMIT之后,并没有RELEASE选项,需要通过调用EXEC SQL DISCONNECT、EXEC SQL CLOSE等命令来实现相关资源的释放。Pro*C中EXEC SQL COMMIT带有RELEASE选项。用于释放程序持有的所有连接、游标等资源信息。 目前ecpg不支持EXEC SQL ENABLE THREAD。 ecpg编译选项中开启宏定义,在main函数的.pgc文件中定义(define)ENABLE_THREAD_SAFETY。 目前ecpg不支持存储过程、匿名块、闪回等特性语法。 父主题: 基于ecpg开发
  • 命名SQL描述符区域 一个命名SQL描述符区域由一个头部以及一个或多个条目描述符区域构成。头部包含与整个描述区域相关的信息,而条目描述符区域则描述结果行中的某一列。 在使用SQL描述符区域之前,需要分配一个SQL描述符区域: EXEC SQL ALLOCATE DESCRIPTOR identifier; 当不再需要这个描述符区域时,应及时释放: EXEC SQL DEALLOCATE DESCRIPTOR identifier; 要使用一个描述符区域,需要使用INTO子句声明: EXEC SQL FETCH NEXT FROM mycursor INTO SQL DESCRIPTOR mydesc; 如果结果集为空,该描述符区域仍会包含查询的元数据。 对于还没有执行的预备查询,可以使用DESCRIBE得到其结果集的元数据: EXEC SQL BEGIN DECLARE SECTION; char *sql_stmt = "SELECT * FROM table1"; EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE stmt1 FROM :sql_stmt; EXEC SQL DESCRIBE stmt1 INTO SQL DESCRIPTOR mydesc; 在DESCRIBE和FETCH语句中,INTO和USING关键词的使用相似:它们产生结果集以及一个描述符区域的元数据。 从头部检索一个描述符区域的值并且将其存储到一个宿主变量中: EXEC SQL GET DESCRIPTOR name :hostvar = field; 当前只定义了一个头部描述符区域COUNT,它存放描述符区域的条目(即结果集中包含多少列),宿主变量为一个整数类型,需从条目描述符区域中得到一个具体值: EXEC SQL GET DESCRIPTOR name VALUE num :hostvar = field; num可以是一个字符整数或者一个包含整数的宿主变量。可能的类型如下: CARDINALITY(整数):结果集中的行数 DATA:实际的数据项(这个范围的实际数据类型取决于查询) DATETIME_INTERVAL_CODE(整数):当TYPE是9时,DATETIME_INTERVAL_CODE将具有以下值之一:1表示DATE,2表示TIME,3表示TIMESTAMP,4表示TIME WITH TIME ZONE,5表示TIMESTAMP WITH TIME ZONE INDICATOR(整数):指示符(表示一个空值或者一个值截断) LENGTH(整数):以字符计的数据长度 NAME(string):列名 OCTET_LENGTH(整数):以字节计的数据字符表达的长度 PRECISION(整数):精度(用于类型numeric) RETURNED_LENGTH(整数):以字符计的数据长度 RETURNED_OCTET_LENGTH(整数):以字节计的数据字符表达的长度 SCALE(整数):比例(用于类型numeric) TYPE(整数):列的数据类型的数字编码 要检索字段数值并且把它存储到一个宿主变量里,使用如下命令: EXEC SQL GET DESCRIPTOR mydesc VALUE num :hostvar = field num可以是一个字符整数或者一个包含整数的宿主变量。可能的字段有: DATA 实际数据项(这个字段的数据类型依赖于这个查询) NAME(string) 字段名称 手动建立一个描述符区域为一个查询或游标提供输入参数,使用如下命令: EXEC SQL SET DESCRIPTOR name VALUE numfield = :hostvar; 在一个FETCH语句中检索多行记录且用数组类型的宿主变量来存储数据,示例如下: EXEC SQL BEGIN DECLARE SECTION; int id[5]; EXEC SQL END DECLARE SECTION; EXEC SQL FETCH 5 FROM mycursor INTO SQL DESCRIPTOR mydesc; EXEC SQL GET DESCRIPTOR mydesc VALUE 1 :id = DATA; 父主题: SQL描述符区域
  • 设置回调 设置回调操作,当告警或者错误发生时,直接执行具体操作进行处理,设置回调命令如下: EXEC SQL WHENEVER condition action; condition取值范围: SQLERROR:当在SQL语句执行期间发生错误时,调用指定操作。 SQLWARNING:当在SQL语句执行期间发生告警时,调用指定操作。 NOT FOUND:当SQL语句检索或者影响为零行时,调用指定操作。 action取值范围: CONTINUE:忽略回调错误条件,继续执行,通常可以用来停止break包含条件,为缺省值。 GOTO label/GO TO label:跳转到指定标签(使用C语言goto语句)。 SQLPRINT:输出消息到标准错误。 STOP:调用exit(1),终止程序。 DO BREAK:执行C语句break,只能在循环中或者switch语句中使用。 示例如下: /* 当出现一个告警时它打印一个消息,发生一个错误时中止程序。 */ EXEC SQL WHENEVER SQLWARNING SQLPRINT; EXEC SQL WHENEVER SQLERROR STOP; 语句EXEC SQL WHENEVER是SQL预处理器的一个指令,而非一个C语言语句。不管C语言程序的流程如何,该语句设置的错误或告警动作都适用于位于处理程序设置点之后的嵌入式SQL语句,除非第一个EXEC SQL WHENEVER语句和导致错误或告警情况发生的SQL语句之间为同一个情况设置了不同的动作。因此下面的两个C语言程序都不会得到预期的效果: /* * 错误 */ void func() { ... if (verbose) { EXEC SQL WHENEVER SQLWARNING SQLPRINT; } ... EXEC SQL SELECT ...; ... } /* * 错误 */ void func() { ... set_error_handler(); ... EXEC SQL SELECT ...; ... } static void set_error_handler(void) { EXEC SQL WHENEVER SQLERROR STOP; } 当使用DO BREAK时只能用于while/for/switch场景,且用完需要使用CONTINUE语句忽略。 父主题: 错误处理
  • 执行没有结果集的语句 执行EXECUTE IMMEDIATE命令示例如下: EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1 (...);"; EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt; EXECUTE IMMEDIATE可以用于不返回结果集的SQL语句,比如:DDL、INSERT、UPDATE和DELETE语句。但不能用这种方式执行检索数据的语句,比如:SELECT语句。 父主题: 执行动态SQL语句
  • 宿主变量 本节详细介绍如何在C语言程序和嵌入式SQL程序之间使用宿主变量传递数据。在嵌入式SQL-C程序中,将C语言作为宿主语言,将EXEC SQL [Command]语句认为是宿主语言的嵌入式SQL,因此将C语言程序中用于嵌入式SQL语句的变量称为宿主变量。 概述 声明段 检索查询 类型映射 处理字符串 使用非初级类型的宿主变量 访问特殊数据类型 处理非初级SQL数据类型 父主题: 基于ecpg开发
  • 查询结果集 返回单行结果的SELECT语句可以直接使用EXEC SQL执行,请参见执行SQL命令章节。 示例: /* 首先建立一个表并插入数据 */ EXEC SQL CREATE TABLE test_table (number1 integer, number2 integer); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (2, 1); /* 查询结果为单行,:num 为宿主变量 */ EXEC SQL SELECT number1 INTO :num FROM test_table WHERE number2 = 1; 若要处理多行结果集,则必须使用游标,请参见使用游标章节(特殊情况下,应用程序可以一次取出多行结果写入到数组类型的宿主变量中,请参见使用非初级类型的宿主变量章节)。 示例: /* 首先建立一个表并插入数据 */ EXEC SQL CREATE TABLE test_table (number1 integer, number2 integer); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (2, 1); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (3, 1); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (4, 1); EXEC SQL INSERT INTO test_table (number1, number2) VALUES (5, 1); /* 定义宿主变量 */ EXEC SQL BEGIN DECLARE SECTION; int v1; int v2; EXEC SQL END DECLARE SECTION; /* 声明游标 */ EXEC SQL DECLARE test_bar CURSOR FOR SELECT number1, number2 FROM test_table ORDER BY number1; /* 打开游标 */ EXEC SQL OPEN test_bar; /* 当游标到达结果集末尾时跳出循环 */ EXEC SQL WHENEVER NOT FOUND DO BREAK; /* 获取查询结果集 */ while(1) { EXEC SQL FETCH NEXT FROM test_bar INTO :v1, :v2; printf("number1 = %d, number2 = %d\n",v1,v2); } /* 关闭游标 */ EXEC SQL CLOSE test_bar; 父主题: 基于ecpg开发
  • 示例 EXEC SQL SET DESCRIPTOR indesc COUNT = 1; EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2; EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = :val1; EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val1, DATA = 'some string'; EXEC SQL SET DESCRIPTOR indesc VALUE 2 INDICATOR = :val2null, DATA = :val2;
  • 示例 char *stmt = "SELECT * FROM test1 WHERE a = ? AND b = ?"; EXEC SQL ALLOCATE DESCRIPTOR outdesc; EXEC SQL PREPARE foo FROM :stmt; EXEC SQL EXECUTE foo USING SQL DESCRIPTOR indesc INTO SQL DESCRIPTOR outdesc;
  • 示例 声明用于查询的游标示例: EXEC SQL DECLARE C CURSOR FOR SELECT * FROM My_Table; EXEC SQL DECLARE C CURSOR FOR SELECT Item1 FROM T; EXEC SQL DECLARE cur1 CURSOR FOR SELECT version(); 声明用于预备语句的游标示例: EXEC SQL PREPARE stmt1 AS SELECT version(); EXEC SQL DECLARE cur1 CURSOR FOR stmt1;
  • 参数说明 connection_target 以下列形式之一指定连接的目标服务器: [ database_name ] [ @host ] [ :port ]:通过TCP/IP连接。 unix:gaussdb://host [ :port ] / [ database_name ] [ ?connection_option ]:通过Unix域套接字连接。 tcp:gaussdb://host [ :port ] / [ database_name ] [ ?connection_option ]:通过TCP/IP连接。 SQL string constant:包含上述形式之一的值。 其他connection_target参数介绍请参见ecpg兼容。 connection_name 用于该连接的一个可选标识符,可以在其他命令中引用它。可以是一个SQL标识符或者一个宿主变量。 connection_user 用于数据库连接的用户名。 使用user_name/password、user_name SQLIDENTIFIED BY password或者user_name USING password之一,这个参数也能指定用户名和密码。 用户名和密码可以是SQL标识符、字符串常量或者宿主变量。 上述参数中斜体部分为变量,请根据实际情况进行修改。
  • 事务管理 在ecpg缺省模式下,语句只有在EXEC SQL COMMIT发出的时候才被提交,嵌入的SQL接口也支持事务的自动提交(通过EXEC SQL SET AUTOCOMMIT TO ON语句设置自动提交)。在自动提交模式下,每条命令都是自动提交的,除非它们包围在一个明确的事务块里。自动提交模式可以用EXEC SQL SET AUTOCOMMIT TO OFF语句关闭。 常见事务管理命令如下: EXEC SQL COMMIT:提交正在进行的事务。 EXEC SQL ROLLBACK:回滚正在进行的事务。 EXEC SQL SET AUTOCOMMIT TO ON:启动自动提交模式。 EXEC SQL SET AUTOCOMMIT TO OFF:关闭自动提交模式,缺省模式。 父主题: 执行SQL命令
  • ecpg组件介绍 ecpg支持平台 表1 ecpg支持平台 操作系统 平台 EulerOS V2.0SP5 x86_64位 EulerOS V2.0SP9 ARM64位 Kylin V10 x86_64位 Kylin V10 ARM64位 ecpg组件 ecpg:用于对嵌入式SQL-C进行预处理的可执行二进制文件。 libecpg:为ecpg提供连接、执行SQL、事务等实现的动态库,包括libecpg.so、libecpg.so.6和libecpg.so.6.4,在C语言程序编译执行时通过“-lecpg”参数引用。 libpgtypes:ecpg提供的用于实现数值、日期、时间戳、区间类型数据操作运算的动态库,包括libpgtypes.so、libecpg.so.6和libecpg.so.6.4,在C语言程序编译执行时通过“-lpgtypes”参数引用。 ecpg组件的获取路径 ecpg二进制获取路径:$GAUSSHOME/bin ecpg依赖动态库路径:$GAUSSHOME/lib ecpg所需头文件路径:$GAUSSHOME/include/ecpg 父主题: 基于ecpg开发
  • 基于ecpg开发 ecpg(embedded SQL C preprocessor for GaussDB Kernel)是一种用于C语言程序的嵌入式SQL预处理器。一个嵌入式SQL程序由一种普通编程语言编写的代码(此处为C语言)和SQL命令共同组成。要构建该程序,源代码(*.pgc)首先通过嵌入式SQL预处理器,将源代码转换成一个普通C语言程序(*.c),然后再通过编译器处理。转换过的ecpg应用通过嵌入式SQL库(ecpglib)调用libpq库中的函数,与GaussDB Kernel服务器使用普通的前端/后端协议通信。 嵌入式SQL程序是插入了数据库相关动作的特殊代码的C语言程序。这种特殊代码形式通常如下: EXEC SQL ...; 这些语句在语法上取代了一个C语句,可以出现在全局或者是一个函数中。嵌入式SQL语句遵循普通SQL代码的大小写敏感规则,也允许嵌套的C语言代码风格注释(SQL标准的一部分)。不过,程序的C语言部分遵循C语言程序的标准,不支持嵌套注释。 开发流程 ecpg组件介绍 ecpg预处理以及编译执行 管理数据库连接 执行SQL命令 查询结果集 关闭数据库连接 宿主变量 执行动态SQL语句 错误处理 预处理指令 使用库函数 SQL描述符区域 常用示例 ecpg与Pro*C兼容性对比 ecpg接口参考 父主题: 应用程序开发教程
  • Psycopg包 准备相关驱动和依赖库。可以从发布包中获取,包名为GaussDB-Kernel_数据库版本号_操作系统版本号_64bit_Python.tar.gz。 解压后有两个文件夹: psycopg2:psycopg2库文件。 lib:lib库文件。 加载驱动。 在使用驱动之前,需要做如下操作: 先解压版本对应驱动包。 tar zxvf xxxx-Python.tar.gz 使用root用户将psycopg2复制到python安装目录下的site-packages文件夹下。 su root cp psycopg2 $(python3 -c 'import site; print(site.getsitepackages()[0])') -r 修改psycopg2目录权限为755。 chmod 755 $(python3 -c 'import site; print(site.getsitepackages()[0])')/psycopg2 -R 将psycopg2目录添加到环境变量$PYTHONPATH,并使之生效。 export PYTHONPATH=$(python3 -c 'import site; print(site.getsitepackages()[0])'):$PYTHONPATH 对于非数据库用户,需要将解压后的lib目录,配置在LD_LIBRARY_PATH中。 export LD_LIBRARY_PATH=path/to/lib:$LD_LIBRARY_PATH 在创建数据库连接之前,需要先加载如下数据库驱动程序: 1 import psycopg2 连接数据库。 非SSL方式连接数据库: 使用psycopg2.connect函数获得connection对象。 使用connection对象创建cursor对象。 SSL方式连接数据库: 用户通过psycopy2连接GaussDB服务器时,可以通过开启SSL加密客户端和服务器之间的通讯。在使用SSL时,默认用户已经获取了服务端和客户端所需要的证书和私钥文件,关于证书等文件的获取请参见Openssl相关文档和命令。 使用*.ini文件(python的configparser包可以解析这种类型的配置文件)保存数据库连接的配置信息。 在连接选项中添加SSL连接相关参数:sslmode、sslcert、sslkey、sslrootcert。 sslmode:可选项见表1。 sslcert:客户端证书路径。 sslkey:客户端密钥路径。 sslrootcert:根证书路径。 使用psycopg2.connect函数获得connection对象。 使用connection对象创建cursor对象。 使用SSL安全连接数据库,需保证所使用的python解释器为生成动态链接库(.so)文件的方式编译,可通过如下步骤确认python解释器的连接方式。 在python解释器命令行中输入import ssl,导入SSL。 执行ps ux查询python解释器运行的pid(假设pid为******)。 在shell命令行中执行pmap -p ****** | grep ssl,查看返回结果中是否包含libssl.so的相关路径。如果有,则python解释器为动态链接方式编译。 表1 sslmode的可选项及其描述 sslmode 是否会启用SSL加密 描述 disable 否 不使用SSL安全连接。 allow 可能 如果数据库服务器要求使用,则可以使用SSL安全加密连接,但不验证数据库服务器的真实性。 prefer 可能 如果数据库支持,那么首选使用SSL连接,但不验证数据库服务器的真实性。 require 是 必须使用SSL安全连接,但是仅进行 数据加密 ,而并不验证数据库服务器的真实性。 verify-ca 是 必须使用SSL安全连接,并且校验服务端CA有效性。 verify-full 是 必须使用SSL安全连接,目前GaussDB暂不支持。 执行SQL语句。 构造操作语句,使用%s作为占位符,执行时psycopg2会用参数值智能替换掉占位符。可以添加RETURNING子句,来得到自动生成的字段值。 使用cursor.execute方法来操作一行SQL语句,使用cursor.executemany方法来操作多行SQL语句。 处理结果集。 cursor.fetchone():这种方法提取的查询结果集的下一行,返回一个序列,没有数据可用时则返回空。 cursor.fetchall():这个方法获取所有查询结果(剩余)行,返回一个列表。空行时则返回空列表。 对于数据库特有数据类型,如tinyint类型,查询结果中相应字段为字符串形式。 关闭连接。 在使用数据库连接完成相应的数据操作后,需要关闭数据库连接。关闭数据库连接可以直接调用其close方法,如connection.close()。 此方法关闭数据库连接,并不自动调用commit()。如果只是关闭数据库连接而不调用commit()方法,那么所有更改将会丢失。 父主题: 基于Psycopg开发
  • 连接参数 表1 连接参数 参数 描述 host 要连接的主机名。如果主机名以斜杠开头,则它声明使用Unix域套接字通讯而不是TCP/IP通讯,该值就是套接字文件所存储的目录。如果没有声明host,那么默认是与位于/tmp目录(或者安装GaussDB的时候声明的套接字目录)里面的Unix-域套接字连接。在没有Unix域套接字的机器上,默认与localhost连接。 接受以“,”分割的字符串来指定多个主机名,支持指定多个主机名。 hostaddr 与之连接的主机的IP地址,是标准的IPv4地址格式,比如,172.28.40.9。如果声明了一个非空的字符串,那么使用TCP/IP通讯机制。 接受以“,”分割的字符串来指定多个IP地址,支持指定多个IP地址。 使用hostaddr取代host可以让应用避免一次主机名查找,这一点对于那些有时间约束的应用来说可能是非常重要的。不过,GSSAPI或SSPI认证方法要求主机名(host)。因此,应用下面的规则: 如果声明了不带hostaddr的host那么就强制进行主机名查找。 如果声明中没有host,hostaddr的值给出服务器网络地址。如果认证方法要求主机名,那么连接尝试将失败。 如果同时声明了host和hostaddr,那么hostaddr的值作为服务器网络地址。host的值将被忽略,除非认证方法需要它,在这种情况下它将被用作主机名。 须知: 如果host不是网络地址hostaddr处的服务器名,那么认证很有可能失败。 如果主机名(host)和主机地址都没有,那么libpq将使用一个本地的Unix域套接字进行连接,或者是在没有Unix域套接字的机器上,它将尝试与localhost连接。 port 主机服务器的端口号,或者在Unix域套接字连接时的套接字扩展文件名。 接受以“,”分割的字符串来指定多个端口号,支持指定多个端口号。 vimuser 要连接的用户名,缺省是与运行该应用的用户操作系统名同名的用户。 dbname 数据库名,缺省和用户名相同。 password 如果服务器要求口令认证,所用的口令。 connect_timeout 连接的最大等待时间,以秒计(用十进制整数字符串书写),0或者不声明表示无穷。不建议把连接超时的值设置小于2秒。 client_encoding 为这个连接设置client_encoding配置参数。除了对应的服务器选项接受的值,可以使用auto从客户端中的当前环境中确定正确的编码(Unix系统上是LC_CTYPE环境变量)。 tty 忽略(以前,该参数指定了发送服务器调试输出的位置)。 options 添加命令行选项以在运行时发送到服务器。 application_name 为application_name配置参数指定一个值,表明当前用户身份。 fallback_application_name 为application_name配置参数指定一个后补值。如果通过一个连接参数或PGAPPNAME环境变量没有为application_name给定一个值,将使用这个值。在一般工具程序中,若设置一个默认名,但不希望这个默认名被用户覆盖,可以通过指定一个后补值来实现。 keepalives 控制客户端侧的TCP保持激活是否使用。缺省值是1,意思为打开,但是如果不想要保持激活,可以更改为0,意思为关闭。通过Unix域套接字做的连接忽略这个参数。 keepalives_idle 在TCP应该发送一个保持激活的信息给服务器之后,控制不活动的秒数。0值表示使用系统缺省。通过Unix域套接字做的连接或者如果禁用了保持激活则忽略这个参数。 keepalives_interval 在TCP保持激活信息没有被应该传播的服务器承认之后,控制秒数。0值表示使用系统缺省。通过Unix域套接字做的连接或者如果禁用了保持激活则忽略这个参数。 keepalives_count 控制TCP发送保持激活信息的次数。0值表示使用系统缺省。通过Unix域套接字做的连接或者如果禁用了保持激活则忽略这个参数。 tcp_user_timeout 在支持TCP_USER_TIMEOUT套接字选项的操作系统上,指定传输的数据在TCP连接被强制关闭之前可以保持未确认状态的最大时长。0值表示使用系统缺省。通过Unix域套接字做的连接忽略这个参数。 tcp_syn_retries 在支持TCP_SYNCNT套接字选项的操作系统上,指定客户端建立连接三次握手阶段SYN包发送失败而重新传输的次数。0值表示使用系统缺省。通过Unix域套接字的连接忽略此参数。 rw_timeout 设置客户端连接读写超时时间。 当libpq侧触发超时且连接关闭时,其下发给数据库侧正在运行的业务会被强制终止。该能力受GUC参数check_disconnect_query控制,设置为on表示支持该能力,设置为off表示不支持该能力。 sslmode 启用SSL加密的方式: disable:不使用SSL安全连接。 allow:如果数据库服务器要求使用,则可以使用SSL安全加密连接,但不验证数据库服务器的真实性。 prefer:如果数据库支持,那么首选使用SSL安全加密连接,但不验证数据库服务器的真实性。 require:必须使用SSL安全连接,但是只做了数据加密,而并不验证数据库服务器的真实性。 verify-ca:必须使用SSL安全连接,当前windows ODBC不支持cert方式认证。 verify-full:必须使用SSL安全连接,当前windows ODBC不支持cert方式认证。 sslcompression 如果设置为1(默认),SSL连接之上传送的数据将被压缩(这要求OpenSSL版本为0.9.8或更高)。如果设置为0,压缩将被禁用(这要求OpenSSL版本为1.0.0或更高)。如果建立的是一个没有SSL的连接,这个参数会被忽略。如果使用的OpenSSL版本不支持该参数,它也会被忽略。压缩会占用CPU时间,但是当瓶颈为网络时可以提高吞吐量。如果CPU性能是限制因素,禁用压缩能够改进响应时间和吞吐量。 sslcert 这个参数指定客户端SSL证书的文件名。如果没有建立SSL连接,这个参数会被忽略。 sslkey 这个参数指定用于客户端证书的密钥位置。它能够指定一个从外部“引擎”(引擎是OpenSSL的可载入模块)得到的密钥。一个外部引擎说明应该由一个冒号分隔的引擎名称以及一个引擎相关的关键标识符组成。如果没有建立SSL连接,这个参数会被忽略。 sslrootcert 这个参数指定一个包含SSL证书机构(CA)证书的文件名称。如果该文件存在,服务器的证书将被验证是由这些机构之一签发。 sslcrl 这个参数指定SSL证书撤销列表(CRL)的文件名。列在这个文件中的证书如果存在,在尝试认证该服务器证书时会被拒绝。 requirepeer 这个参数指定服务器的操作系统用户,例如requirepeer=postgres。当建立一个Unix域套接字连接时,如果设置了这个参数,客户端在连接开始时检查服务器进程是否运行在指定的用户名之下。如果发现不是,该连接会被一个错误中断。这个参数能被用来提供与TCP/IP连接上SSL证书相似的服务器认证(注意,如果Unix域套接字在/tmp或另一个公共可写的位置,任何用户能启动一个在那里侦听的服务器。使用这个参数来保证所连接的是一个由可信用户运行的服务器)。这个选项只在实现了peer认证方法的平台上支持。 krbsrvname 当用GSSAPI认证时,要使用的Kerberos服务名。为了让Kerberos认证成功,这必须匹配在服务器配置中指定的服务名。 gsslib 用于GSSAPI认证的GSS库。只用在Windows上。设置为gssapi可强制libpq用GSSAPI库来代替默认的SSPI进行认证。 service 用于附加参数的服务名。它指定保持附加连接参数的pg_service.conf中的一个服务名。这允许应用只指定一个服务名,这样连接参数能被集中维护。 authtype 不再使用“authtype”,因此将其标记为“不显示”。将其保留在数组中,以免拒绝旧应用程序中的conninfo字符串,这些应用程序可能仍在尝试设置它。 remote_nodename 指定连接本地节点的远端节点名称。 localhost 指定在一个连接通道中的本地地址。 localport 指定在一个连接通道中的本地端口。 fencedUdfRPCMode 控制fenced UDF RPC协议是使用unix域套接字或特殊套接字文件名。缺省值是0,意思为关闭。使用unix domain socket模式,文件类型为“.s.PGSQL.%d”;但是要使用fenced udf ,文件类型为.s.fencedMaster_unixdomain,可以更改为1,意思为开启。 replication 这个选项决定是否该连接应该使用复制协议而不是普通协议。这是PostgreSQL的复制连接以及pg_basebackup之类的工具在内部使用的协议,但也可以被第三方应用使用。支持下列值,大小写无关: true、on、yes、1 连接进入到物理复制模式。 database 连接进入到逻辑复制模式,连接到dbname参数中指定的数据库。 false、off、no、0 该连接是一个常规连接,这是默认行为。 在物理或者逻辑复制模式中,仅能使用简单查询协议。 backend_version 传递到远端的后端版本号。 prototype 设置当前协议级别,默认:PROTO_TCP。 enable_ce 控制是否允许客户端连接全密态数据库。默认值为0,不开启密态功能。如果需要开启密态等值查询基本能力,则修改为1。修改为3的时候,仅支持密态等值查询的基本能力。 key_info 与enable_ce一起使用,在密态数据库中,用于设置访问外部密钥管理者的参数。 connection_info Connection_info是一个包含driver_name、driver_version、driver_path和os_user的json字符串。 如果不为NULL,使用connection_info 忽略connectionExtraInf。 如果为NULL,生成与libpq相关的连接信息字符串,当connectionExtraInf为false时connection_info只有driver_name和driver_version。 connectionExtraInf 设置connection_info是否存在扩展信息,默认值为0,如果包含其他信息,则需要设置为1。 target_session_attrs 设定连接的主机的类型。主机的类型和设定的值一致时才能连接成功。指定多IP时才会校验此参数。target_session_attrs的设置规则如下: any:可以对所有类型的主机进行连接。 read-write:当连接的主机允许可读可写时,才进行连接。 read-only:仅对可读的主机进行连接。 primary(默认值):仅对主备系统中的主机能进行连接。 standby:仅对主备系统中的备机进行连接。 prefer-standby:首先尝试找到一个备机进行连接。如果对hosts列表的所有机器都连接失败,那么尝试“any”模式进行连接。 父主题: 基于libpq开发
  • 注意事项 在非阻塞连接上发送任何命令或数据之后,调用PQflush。如果返回1,则等待套接字变为读或写就绪。如果为写就绪状态,则再次调用PQflush。如果已经读到,调用PQconsumeInput,然后再次调用PQflush。重复,直到PQflush返回0。(必要检查读就绪并使用PQconsumeInput耗尽输入,因为服务器可能会阻止尝试向客户端发送数据(例如NOTICE消息),并且在客户端读取它的数据之前不会读取客户端的数据。)一旦PQflush返回0,等待套接字准备好,然后按照上面描述读取响应。
  • 原型 int PQsendQueryParams(PGconn* conn, const char* command, int nParams, const Oid* paramTypes, const char* const* paramValues, const int* paramLengths, const int* paramFormats, int resultFormat);
共100000条