华为云用户手册

  • 操作步骤 方法一: 声明字段类型为序列整型来定义标识符字段。例如: 12345 openGauss=# CREATE TABLE T1( id serial, name text); 当结果显示为如下信息,则表示创建成功。 1 CREATE TABLE 方法二: 创建序列,并通过nextval('sequence_name')函数指定为某一字段的默认值。这种方式更灵活,可以为序列定义cache,一次预申请多个序列值,减少与GTM的交互次数,来提高性能。 创建序列 1 openGauss=# CREATE SEQUENCE seq1 cache 100; 当结果显示为如下信息,则表示创建成功。 1 CREATE SEQUENCE 指定为某一字段的默认值,使该字段具有唯一标识属性。 12345 openGauss=# CREATE TABLE T2 ( id int not null default nextval('seq1'), name text); 当结果显示为如下信息,则表示默认值指定成功。 1 CREATE TABLE 指定序列与列的归属关系。 将序列和一个表的指定字段进行关联。这样,在删除那个字段或其所在表的时候会自动删除已关联的序列。 1 openGauss=# ALTER SEQUENCE seq1 OWNED BY T2.id; 当结果显示为如下信息,则表示指定成功。 1 ALTER SEQUENCE 除了为序列指定了cache,方法二所实现的功能基本与方法一类似。但是一旦定义cache,序列将会产生空洞(序列值为不连贯的数值,如:1.4.5),并且不能保序。另外为某序列指定从属列后,该列删除,对应的sequence也会被删除。 虽然数据库并不限制序列只能为一列产生默认值,但建议不要多列共用同一个序列。 当前版本只支持在定义表的时候指定自增列,或者指定某列的默认值为nextval('seqname'), 不支持在已有表中增加自增列或者增加默认值为nextval('seqname')的列。
  • 注意事项 新序列值的产生是靠GTM维护的,默认情况下,每申请一个序列值都要向GTM发送一次申请,GTM在当前值的基础上加上步长值作为产生的新值返回给调用者。GTM作为全局唯一的节点,势必成为性能的瓶颈,所以对于需要大量频繁产生序列号的操作,如使用Bulkload工具进行数据导入场景,是非常不推荐产生默认序列值的。比如,在下面所示的场景中, INSERT FROM SELECT语句的性能会非常慢。 1234567 openGauss=# CREATE SEQUENCE newSeq1;openGauss=# CREATE TABLE newT1 ( id int not null default nextval('newSeq1'), name text );openGauss=# INSERT INTO newT1(name) SELECT name from T1; 可以提高性能的写法是(假设T1表导入newT1表中的数据为10000行): 12 openGauss=# INSERT INTO newT1(id, name) SELECT id,name from T1;openGauss=# SELECT SETVAL('newSeq1',10000); 序列操作函数nextval(),setval() 等均不支持回滚。另外setval设置的新值,会对当前会话的nextval立即生效,但对其他会话,如果定义了cache,不会立即生效,在用尽所有缓存的值后,其变动才被其他会话感知。所以为了避免产生重复值,要谨慎使用setval,设置的新值不能是已经产生的值或者在缓存中的值。 如果必须要在bulkload场景下产生默认序列值,则一定要为newSeq1定义足够大的cache,并且不要定义Maxvalue或者Minvalue。数据库会试图将nextval('sequence_name')的调用下推到Data Node,以提高性能。 目前GTM对并发的连接请求是有限制的,当Data Node很多时,将产生大量并发连接, 这时一定要控制bulkload的并发数目,避免耗尽GTM的连接资源。如果目标表为复制表(DISTRIBUTE BY REPLICATION)时下推将不能进行。当数据量较大时,这对数据库将是个灾难。除了性能问题之外,空间也可能会剧烈膨胀,在导入结束后,需要用vacuum full来恢复。推荐采用如上建议,不要在bulkload的场景中产生默认序列值。 另外,序列创建后,在每个节点上都维护了一张单行表,存储序列的定义及当前值,但此当前值并非GTM上的当前值,只是保存本节点与GTM交互后的状态。如果其他节点也向GTM申请了新值,或者调用了Setval修改了序列的状态,不会刷新本节点的单行表,但因每次申请序列值是向GTM申请,所以对序列正确性没有影响。
  • 背景信息 GaussDB数据库 支持的分区表为范围分区表。 范围分区表:将数据基于范围映射到每一个分区,这个范围是由创建分区表时指定的分区键决定的。这种分区方式是最为常用的,并且分区键经常采用日期,例如将销售数据按照月份进行分区。 分区表和普通表相比具有以下优点: 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索效率。 增强可用性:如果分区表的某个分区出现故障,表在其他分区的数据仍然可用。 方便维护:如果分区表的某个分区出现故障,需要修复数据,只修复该分区即可。 普通表若要转成分区表,需要新建分区表,然后把普通表中的数据导入到新建的分区表中。因此在初始设计表时,请根据业务提前规划是否使用分区表。
  • 数据库对象命名 数据库对象命名需要满足约束:非时序表长度不超过63个字节,时序表长度不超过53个字符,以字母或下划线开头,中间字符可以是字母、数字、下划线、$、#。 【建议】避免使用保留或者非保留关键字命名数据库对象。 可以使用select * from pg_get_keywords()查询 GaussDB 的关键字,或者在关键字章节中查看。 【建议】避免使用双引号括起来的字符串来定义数据库对象名称,除非需要限制数据库对象名称的大小写。数据库对象名称大小写敏感会使定位问题难度增加。 【建议】数据库对象命名风格务必保持统一。 增量开发的业务系统或进行业务迁移的系统,建议遵守历史的命名风格。 建议使用多个单词组成,以下划线分割。 数据库对象名称建议能够望文知意,尽量避免使用自定义缩写(可以使用通用的术语缩写进行命名)。例如,在命名中可以使用具有实际业务含义的英文词汇或汉语拼音,但规则应该在集群范围内保持一致。 变量名的关键是要具有描述性,即变量名称要有一定的意义,变量名要有前缀标明该变量的类型。 【建议】表对象的命名应该可以表征该表的重要特征。例如,在表对象命名时区分该表是普通表、临时表还是非日志表: 普通表名按照数据集的业务含义命名。 临时表以“tmp_+后缀”命名。 非日志表以“ul_+后缀”命名。 外表以“f_+后缀”命名。 不创建以redis_为前缀的数据库对象。 不创建以mlog_和以matviewmap_为前缀的数据库对象。 【建议】非时序表对象命名建议不要超过63字节。如果超过该长度内核会对表名进行截断,从而出现实际名称和设置值不一致的现象;且在不同字符集下,可能造成字符被截断,出现预期外的字符。 父主题: 开发设计建议
  • 背景信息 索引可以提高数据的访问速度,但同时也增加了插入、更新和删除操作的处理时间。所以是否要为表增加索引,索引建立在哪些字段上,是创建索引前必须要考虑的问题。需要分析应用程序的业务处理、数据使用、经常被用作查询的条件或者被要求排序的字段来确定是否建立索引。 索引建立在数据库表中的某些列上。因此,在创建索引时,应该仔细考虑在哪些列上创建索引。 在经常需要搜索查询的列上创建索引,可以加快搜索的速度。 在作为主键的列上创建索引,强制该列的唯一性和组织表中数据的排列结构。 在经常使用连接的列上创建索引,这些列主要是一些外键,可以加快连接的速度。 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的。 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。 在经常使用WHERE子句的列上创建索引,加快条件的判断速度。 为经常出现在关键字ORDER BY、GROUP BY、DISTINCT后面的字段建立索引。 索引创建成功后,系统会自动判断何时引用索引。当系统认为使用索引比顺序扫描更快时,就会使用索引。 索引创建成功后,必须和表保持同步以保证能够准确地找到新数据,这样就增加了数据操作的负荷。因此请定期删除无用的索引。
  • 注意事项 数据库集群包含一个或多个已命名数据库。用户和用户组在整个集群范围内是共享的,但是其数据并不共享。任何与服务器连接的用户都只能访问连接请求里声明的那个数据库。 一个数据库可以包含一个或多个已命名的schema,schema又包含表及其他数据库对象,包括数据类型、函数、操作符等。同一对象名可以在不同的schema中使用而不会引起冲突。例如,schema1和schema2都可以包含一个名为mytable的表。 和数据库不同,schema不是严格分离的。用户根据其对schema的权限,可以访问所连接数据库的schema中的对象。进行schema权限管理首先需要对数据库的权限控制进行了解。 不能创建以PG_为前缀的schema名,该类schema为数据库系统预留的。 在每次创建新用户时,系统会在当前登录的数据库中为新用户创建一个同名Schema。对于其他数据库,若需要同名Schema,则需要用户手动创建。 通过未修饰的表名(名称中只含有表名,没有“schema名”)引用表时,系统会通过search_path(搜索路径)来判断该表是哪个schema下的表。pg_temp和pg_catalog始终会作为搜索路径顺序中的前两位,无论二者是否出现在search_path中,或者出现在search_path中的任何位置。search_path(搜索路径)是一个schema名列表,在其中找到的第一个表就是目标表,如果没有找到则报错。(某个表即使存在,如果它的schema不在search_path中,依然会查找失败)在搜索路径中的第一个schema叫做"当前schema"。它是搜索时查询的第一个schema,同时在没有声明schema名时,新创建的数据库对象会默认存放在该schema下。 每个数据库都包含一个pg_catalog schema,它包含系统表和所有内置数据类型、函数、操作符。pg_catalog是搜索路径中的一部分,始终在临时表所属的模式后面,并在search_path中所有模式的前面,即具有第二搜索优先级。这样确保可以搜索到数据库内置对象。如果用户需要使用和系统内置对象重名的自定义对象时,可以在操作自定义对象时带上自己的模式。
  • 操作步骤 创建schema 执行如下命令来创建一个schema。 1 openGauss=# CREATE SCHEMA myschema; 当结果显示为如下信息,则表示成功创建一个名为myschema的schema。 1 CREATE SCHEMA 如果需要在模式中创建或者访问对象,其完整的对象名称由模式名称和具体的对象名称组成。中间由符号“.”隔开。例如:myschema.table。 执行如下命令在创建schema时指定owner。 1 openGauss=# CREATE SCHEMA myschema AUTHORIZATION omm; 当结果显示为如下信息,则表示成功创建一个属于omm用户,名为myschema的schema。 1 CREATE SCHEMA 使用schema 在特定schema下创建对象或者访问特定schema下的对象,需要使用有schema修饰的对象名。该名称包含schema名以及对象名,他们之间用“.”号分开。 执行如下命令在myschema下创建mytable表。 12 openGauss=# CREATE TABLE myschema.mytable(id int, name varchar(20));CREATE TABLE 如果在数据库中指定对象的位置,就需要使用有schema修饰的对象名称。 执行如下命令查询myschema下mytable表的所有数据。 1234 openGauss=# SELECT * FROM myschema.mytable;id | name ----+------(0 rows) schema的搜索路径 可以设置search_path配置参数指定寻找对象可用schema的顺序。在搜索路径列出的第一个schema会变成默认的schema。如果在创建对象时不指定schema,则会创建在默认的schema中。 执行如下命令查看搜索路径。 12345 openGauss=# SHOW SEARCH_PATH; search_path---------------- "$user",public(1 row) 执行如下命令将搜索路径设置为myschema、public,首先搜索myschema。 12 openGauss=# SET SEARCH_PATH TO myschema, public;SET schema的权限控制 默认情况下,用户只能访问属于自己的schema中的数据库对象。如果需要访问其他schema的对象,则该schema的所有者应该赋予他对该schema的usage权限。 通过将模式的CREATE权限授予某用户,被授权用户就可以在此模式中创建对象。注意默认情况下,所有角色都拥有在public模式上的USAGE权限,但是普通用户没有在public模式上的CREATE权限。普通用户能够连接到一个指定数据库并在它的public模式中创建对象是不安全的,如果普通用户具有在public模式上的CREATE权限则建议通过如下语句撤销该权限。 撤销PUBLIC在public模式下创建对象的权限,下面语句中第一个“public”是模式,第二个“PUBLIC”指的是所有角色。 12 openGauss=# REVOKE CREATE ON SCHEMA public FROM PUBLIC;REVOKE 使用以下命令查看现有的schema: 12345 openGauss=# SELECT current_schema(); current_schema ---------------- myschema(1 row) 执行如下命令创建用户jack,并将myschema的usage权限赋给用户jack。 1234 openGauss=# CREATE USER jack IDENTIFIED BY 'xxxxxxxxxx';CREATE ROLEopenGauss=# GRANT USAGE ON schema myschema TO jack;GRANT 将用户jack对于myschema的usage权限收回。 12 openGauss=# REVOKE USAGE ON schema myschema FROM jack;REVOKE 删除schema 当schema为空时,即该schema下没有数据库对象,使用DROP SCHEMA命令进行删除。例如删除名为nullschema的空schema。 12 openGauss=# DROP SCHEMA IF EXISTS nullschema;DROP SCHEMA 当schema非空时,如果要删除一个schema及其包含的所有对象,需要使用CASCADE关键字。例如删除myschema及该schema下的所有对象。 12 openGauss=# DROP SCHEMA myschema CASCADE;DROP SCHEMA 执行如下命令删除用户jack。 12 openGauss=# DROP USER jack;DROP ROLE
  • 查看和停止正在运行的查询语句 通过视图PG_STAT_ACTIVITY可以查看正在运行的查询语句。方法如下: 设置参数track_activities为on。 1 SET track_activities = on; 当此参数为on时,数据库系统才会收集当前活动查询的运行信息。 查看正在运行的查询语句。以查看正在运行的查询语句所连接的数据库名、执行查询的用户、查询状态及查询对应的PID为例: 1 SELECT datname, usename, state,pid FROM pg_stat_activity; 12345678 datname | usename | state | pid----------+---------+--------+----------------- postgres | Ruby | active | 140298793514752 postgres | Ruby | active | 140298718004992 postgres | Ruby | idle | 140298650908416 postgres | Ruby | idle | 140298625742592 postgres | omm | active | 140298575406848(5 rows) 如果state字段显示为idle,则表明此连接处于空闲,等待用户输入命令。 如果仅需要查看非空闲的查询语句,则使用如下命令查看: 1 SELECT datname, usename, state pid FROM pg_stat_activity WHERE state != 'idle'; 若需要取消运行时间过长的查询,通过PG_TERMINATE_BACKEND函数,根据线程ID(即2中查询结果的pid字段)结束会话。 1 SELECT PG_TERMINATE_BACKEND(140298793514752); 显示类似如下信息,表示结束会话成功。 1234 PG_TERMINATE_BACKEND---------------------- t(1 row) 显示类似如下信息,表示用户执行了结束当前会话的操作。 12 FATAL: terminating connection due to administrator commandFATAL: terminating connection due to administrator command 1. gsql客户端使用PG_TERMINATE_BACKEND函数结束当前正在执行会话的后台线程时,如果当前的用户是初始用户,客户端不会退出而是自动重连,即还会返回“The connection to the server was lost. Attempting reset: Succeeded.”;否则客户端会重连失败,即返回“The connection to the server was lost. Attempting reset: Failed.”。这是因为只有初始用户可以免密登录,普遍用户不能免密登录,从而重连失败。 2. 对于使用PG_TERMINATE_BACKEND函数结束非活跃的后台线程时。如果打开了线程池,此时空闲的会话没有线程ID,无法结束会话。非线程池模式下,结束的会话不会自动重连。
  • 查看数据库用户 通过PG_USER可以查看数据库中所有用户的列表,还可以查看用户ID(USESYSID)和用户权限。 1 SELECT * FROM pg_user; 123456 usename | usesysid | usecreatedb | usesuper | usecatupd | userepl | passwd | valbegin | valuntil | respool | parent | spacelimit | useconfig | nodegroup | tempspacelimit | spillspacelimit ---------+----------+-------------+----------+-----------+---------+----------+----------+----------+--------------+-------------+------------+-----------+-----------+----------------+----------------- roach | 10 | t | t | t | t | ******** | | | default_pool | 0 | | | | | (1 row)
  • 查看数据库中包含的表 例如,在PG_TABLES系统表中查看public schema中包含的所有表。 1 SELECT distinct(tablename) FROM pg_tables WHERE SCHEMANAME = 'public'; 结果类似如下这样: 123456789 tablename------------------- err_hr_staffs test err_hr_staffs_ft3 web_returns_p1 mig_seq_table films4(6 rows)
  • 背景信息 当用户对数据库中的一张或者多张表的某些字段的组合感兴趣,而又不想每次键入这些查询时,用户就可以定义一个视图,以便解决这个问题。 视图与基本表不同,不是物理上实际存在的,是一个虚表。数据库中仅存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。若基本表中的数据发生变化,从视图中查询出的数据也随之改变。从这个意义上讲,视图就像一个窗口,透过它可以看到数据库中用户感兴趣的数据及变化。视图每次被引用的时候都会运行一次。
  • 更新表中数据 修改已经存储在数据库中数据的行为叫做更新。用户可以更新单独一行,所有行或者指定的部分行。还可以独立更新每个字段,而其他字段则不受影响。 使用UPDATE命令更新现有行,需要提供以下三种信息: 表的名称和要更新的字段名 字段的新值 要更新哪些行 SQL通常不会为数据行提供唯一标识,因此无法直接声明需要更新哪一行。但是可以通过声明一个被更新的行必须满足的条件。只有在表里存在主键的时候,才可以通过主键指定一个独立的行。 建立表和插入数据的步骤请参考创建表和向表中插入数据。 需要将表customer_t1中c_customer_sk为9527的地域重新定义为9876: 1 openGauss=# UPDATE customer_t1 SET c_customer_sk = 9876 WHERE c_customer_sk = 9527; 这里的表名称也可以使用模式名修饰,否则会从默认的模式路径找到这个表。SET后面紧跟字段和新的字段值。新的字段值不仅可以是常量,也可以是变量表达式。 比如,把所有c_customer_sk的值增加100: 1 openGauss=# UPDATE customer_t1 SET c_customer_sk = c_customer_sk + 100; 在这里省略了WHERE子句,表示表中的所有行都要被更新。如果出现了WHERE子句,那么只有匹配其条件的行才会被更新。 在SET子句中的等号是一个赋值,而在WHERE子句中的等号是比较。WHERE条件不一定是相等测试,许多其他的操作符也可以使用。 用户可以在一个UPDATE命令中更新更多的字段,方法是在SET子句中列出更多赋值,比如: 1 openGauss=# UPDATE customer_t1 SET c_customer_id = 'Admin', c_first_name = 'Local' WHERE c_customer_sk = 4421; 批量更新或删除数据后,会在数据文件中产生大量的删除标记,查询过程中标记删除的数据也是需要扫描的。故多次批量更新/删除后,标记删除的数据量过大会严重影响查询的性能。建议在批量更新/删除业务会反复执行的场景下,定期执行VACUUM FULL以保持查询性能。 父主题: 创建和管理表
  • 操作步骤 向表中插入数据前,意味着表已创建成功。创建表的步骤请参考创建和管理表。 向表customer_t1中插入一行: 数据值是按照这些字段在表中出现的顺序列出的,并且用逗号分隔。通常数据值是文本(常量),但也允许使用标量表达式。 1 openGauss=# INSERT INTO customer_t1(c_customer_sk, c_customer_id, c_first_name) VALUES (3769, 'hello', 'Grace'); 如果用户已经知道表中字段的顺序,也可无需列出表中的字段。例如以下命令与上面的命令效果相同。 1 openGauss=# INSERT INTO customer_t1 VALUES (3769, 'hello', 'Grace'); 如果用户不知道所有字段的数值,可以忽略其中的一些。没有数值的字段将被填充为字段的缺省值。例如: 123 openGauss=# INSERT INTO customer_t1 (c_customer_sk, c_first_name) VALUES (3769, 'Grace');openGauss=# INSERT INTO customer_t1 VALUES (3769, 'hello'); 用户也可以对独立的字段或者整个行明确缺省值: 123 openGauss=# INSERT INTO customer_t1 (c_customer_sk, c_customer_id, c_first_name) VALUES (3769, 'hello', DEFAULT);openGauss=# INSERT INTO customer_t1 DEFAULT VALUES; 如果需要在表中插入多行,请使用以下命令: 1234 openGauss=# INSERT INTO customer_t1 (c_customer_sk, c_customer_id, c_first_name) VALUES (6885, 'maps', 'Joes'), (4321, 'tpcds', 'Lily'), (9527, 'world', 'James'); 如果需要向表中插入多条数据,除此命令外,也可以多次执行插入一行数据命令实现。但是建议使用此命令可以提升效率。 如果从指定表插入数据到当前表,例如在数据库中创建了一个表customer_t1的备份表customer_t2,现在需要将表customer_t1中的数据插入到表customer_t2中,则可以执行如下命令。 123456789 openGauss=# CREATE TABLE customer_t2( c_customer_sk integer, c_customer_id char(5), c_first_name char(6), c_last_name char(8));openGauss=# INSERT INTO customer_t2 SELECT * FROM customer_t1; 从指定表插入数据到当前表时,若指定表与当前表对应的字段数据类型之间不存在隐式转换,则这两种数据类型必须相同。 删除备份表 1 openGauss=# DROP TABLE customer_t2 CASCADE; 在删除表的时候,若当前需删除的表与其他表有依赖关系,需先删除关联的表,然后再删除当前表。
  • 背景信息 服务端与客户端使用不同的字符集时,两者字符集中单个字符的长度也会不同,客户端输入的字符串会以服务端字符集的格式进行处理,所以产生的最终结果可能会与预期不一致。 表1 客户端和服务端设置字符集的输出结果对比 操作过程 服务端和客户端编码一致 服务端和客户端编码不一致 存入和取出过程中没有对字符串进行操作 输出预期结果 输出预期结果(输入与显示的客户端编码必须一致)。 存入取出过程对字符串有做一定的操作(如字符串函数操作) 输出预期结果 根据对字符串具体操作可能产生非预期结果。 存入过程中对超长字符串有截断处理 输出预期结果 字符集中字符编码长度是否一致,如果不一致可能会产生非预期的结果。 上述字符串函数操作和自动截断产生的效果会有叠加效果,例如:在客户端与服务端字符集不一致的场景下,如果既有字符串操作,又有字符串截断,在字符串被处理完以后的情况下继续截断,这样也会产生非预期的效果。详细的示例请参见表2。 数据库DBCOMPATIBILITY设为兼容TD(Teradata)模式,且td_compatible_truncation参数设置为on的情况下,才会对超长字符串进行截断。 执行如下命令建立示例中需要使用的表table1、table2。 12 openGauss=# CREATE TABLE table1(id int, a char(6), b varchar(6),c varchar(6));openGauss=# CREATE TABLE table2(id int, a char(20), b varchar(20),c varchar(20)); 表2 示例 编号 服务端字符集 客户端字符集 是否启用自动截断 示例 结果 说明 1 SQL_ASCII UTF8 是 1 openGauss=# INSERT INTO table1 VALUES(1,reverse('123AA78'),reverse('123AA78'),reverse('123AA78')); 123 id |a|b|c----+------+------+------1 | 87| 87| 87 字符串在服务端翻转后,并进行截断,由于服务端和客户端的字符集不一致,字符A在客户端由多个字节表示,结果产生异常。 2 SQL_ASCII UTF8 是 1 openGauss=# INSERT INTO table1 VALUES(2,reverse('123A78'),reverse('123A78'),reverse('123A78')); 123 id |a|b|c----+------+------+------2 | 873| 873| 873 字符串翻转后,又进行了自动截断,所以产生了非预期的效果。 3 SQL_ASCII UTF8 是 1 openGauss=# INSERT INTO table1 VALUES(3,'87A123','87A123','87A123'); 123 id | a | b | c----+-------+-------+------- 3 | 87A1 | 87A1 | 87A1 字符串类型的字段长度是客户端字符编码长度的整数倍,所以截断后产生结果正常。 4 SQL_ASCII UTF8 否 12 openGauss=# INSERT INTO table2 VALUES(1,reverse('123AA78'),reverse('123AA78'),reverse('123AA78'));openGauss=# INSERT INTO table2 VALUES(2,reverse('123A78'),reverse('123A78'),reverse('123A78')); 1234 id |a|b|c----+-------------------+--------+--------1 | 87 321| 87 321 | 87 3212 | 87321| 87321| 87321 与示例1类似,多字节字符翻转之后不再表示原来的字符。
  • 删除表中数据 在使用表的过程中,可能会需要删除已过期的数据,删除数据必须从表中整行的删除。 SQL不能直接访问独立的行,只能通过声明被删除行匹配的条件进行。如果表中有一个主键,用户可以指定准确的行。用户可以删除匹配条件的一组行或者一次删除表中的所有行。 使用DELETE命令删除行,如果删除表customer_t1中所有c_customer_sk为3869的记录: 1 openGauss=# DELETE FROM customer_t1 WHERE c_customer_sk = 3869; 如果执行如下命令之一,会删除表中所有的行。 1 openGauss=# DELETE FROM customer_t1; 12 或:openGauss=# TRUNCATE TABLE customer_t1; 全表删除的场景下,建议使用truncate,不建议使用delete。 删除创建的表: 1 openGauss=# DROP TABLE customer_t1; 父主题: 创建和管理表
  • 查看数据 使用系统表pg_tables查询数据库所有表的信息。 1 openGauss=# SELECT * FROM pg_tables; 使用gsql的\d+命令查询表的属性。 1 openGauss=# \d+ customer_t1; 执行如下命令查询表customer_t1的数据量。 1 openGauss=# SELECT count(*) FROM customer_t1; 执行如下命令查询表customer_t1的所有数据。 1 openGauss=# SELECT * FROM customer_t1; 执行如下命令只查询字段c_customer_sk的数据。 1 openGauss=# SELECT c_customer_sk FROM customer_t1; 执行如下命令过滤字段c_customer_sk的重复数据。 1 openGauss=# SELECT DISTINCT( c_customer_sk ) FROM customer_t1; 执行如下命令查询字段c_customer_sk为3869的所有数据。 1 openGauss=# SELECT * FROM customer_t1 WHERE c_customer_sk = 3869; 执行如下命令按照字段c_customer_sk进行排序。 1 openGauss=# SELECT * FROM customer_t1 ORDER BY c_customer_sk; 父主题: 创建和管理表
  • 背景信息 通过使用表空间,管理员可以控制一个数据库安装的磁盘布局。这样有以下优点: 如果初始化数据库所在的分区或者卷空间已满,又不能逻辑上扩展更多空间,可以在不同的分区上创建和使用表空间,直到系统重新配置空间。 表空间允许管理员根据数据库对象的使用模式安排数据位置,从而提高性能。 一个频繁使用的索引可以放在性能稳定且运算速度较快的磁盘上,比如一种固态设备。 一个存储归档的数据,很少使用的或者对性能要求不高的表可以存储在一个运算速度较慢的磁盘上。 管理员通过表空间可以设置占用的磁盘空间。用以在和其他数据共用分区的时候,防止表空间占用相同分区上的其他空间。 表空间可以控制数据库数据占用的磁盘空间,当表空间所在磁盘的使用率达到90%时,数据库将被设置为只读模式,当磁盘使用率降到90%以下时,数据库将恢复到读写模式。 CM的磁盘自动检查功能默认是开启的,使用如下方式开启CM的磁盘自动检查功能: gs_guc set -Z cmserver -N all -I all -c " enable_transaction_read_only = on " 重启数据库使参数设置生效。 表空间对应于一个文件系统目录,采用如下命令创建一个对应/pg_location/mount1/path1的表空间,并指定最大可使用空间为500GB。 12 --创建表空间。openGauss=# CREATE TABLESPACE ds_location1 RELATIVE LOCATION '/pg_location/mount1/path1' MAXSIZE '500G'; 通过MAXSIZE进行表空间配额管理对并发插入性能可能会有30%左右的影响,MAXSIZE指定每个DN的配额大小,每个DN实际的表空间容量和配额误差在500MB以内。请根据实际的情况确认是否需要设置表空间的最大值。 GaussDB自带了两个表空间:pg_default和pg_global。 默认表空间pg_default:用来存储非共享系统表、用户表、用户表index、临时表、临时表index、内部临时表的默认表空间。对应存储目录为实例数据目录下的base目录。 共享表空间pg_global:用来存放共享系统表的表空间。对应存储目录为实例数据目录下的global目录。
  • 操作步骤 创建表空间 执行如下命令创建用户jack。 1 openGauss=# CREATE USER jack IDENTIFIED BY 'xxxxxxxxx'; 当结果显示为如下信息,则表示创建成功。 1 CREATE ROLE 执行如下命令创建表空间。 1 openGauss=# CREATE TABLESPACE fastspace RELATIVE LOCATION 'my_tablespace/tablespace1'; 当结果显示为如下信息,则表示创建成功。 1 CREATE TABLESPACE 其中“fastspace”为新创建的表空间,“CN和DN数据目录/pg_location/my_tablespace/tablespace1”是用户拥有读写权限的空目录。 数据库系统管理员执行如下命令将“fastspace”表空间的访问权限赋予数据用户jack。 1 openGauss=# GRANT CREATE ON TABLESPACE fastspace TO jack; 当结果显示为如下信息,则表示赋予成功。 1 GRANT
  • 操作步骤 使用如下命令创建一个新的数据库db_tpcds。 12 openGauss=# CREATE DATABASE db_tpcds;CREATE DATABASE 数据库名称遵循SQL标识符的一般规则。当前角色自动成为此新数据库的所有者。 如果一个数据库系统用于承载相互独立的用户和项目,建议把它们放在不同的数据库里。 如果项目或者用户是相互关联的,并且可以相互使用对方的资源,则应该把它们放在同一个数据库里,但可以规划在不同的模式中。模式只是一个纯粹的逻辑结构,某个模式的访问权限由权限系统模块控制。 创建数据库时,若数据库名称长度超过63字节,server端会对数据库名称进行截断,保留前63个字节,因此建议数据库名称长度不要超过63个字节。 查看数据库 使用\l元命令查看数据库系统的数据库列表。 1 openGauss=# \l 使用如下命令通过系统表pg_database查询数据库列表。 1 openGauss=# SELECT datname FROM pg_database; 修改数据库。 用户可以使用如下命令修改数据库属性(比如:owner、名称和默认的配置属性)。 使用如下命令为数据库重新命名。 12 openGauss=# ALTER DATABASE db_tpcds RENAME TO human_tpcds;ALTER DATABASE 执行完参数设置后,需要手动执行CLEAN CONNECTION清理旧连接,否则可能存在节点间参数值不一致。 删除数据库 用户可以使用DROP DATABASE命令删除数据库。这个命令删除了数据库中的系统目录,并且删除了带有数据的磁盘上的数据库目录。用户必须是数据库的owner或者系统管理员才能删除数据库。当有人连接数据库时,删除操作会失败。删除数据库时请先连接到其他的数据库。 使用如下命令删除数据库: 12 openGauss=# DROP DATABASE human_tpcds;DROP DATABASE
  • 背景信息 初始时,GaussDB包含两个模板数据库template0、template1,以及一个默认的用户数据库postgres。 CREATE DATABASE实际上通过拷贝模板数据库来创建新数据库。只支持拷贝template0。请避免使用客户端或其他手段连接及操作两个模板数据库。 模板数据库中没有用户表,可通过系统表PG_DATABASE查看模板数据库属性。 模板template0不允许用户连接;模板template1只允许数据库初始用户和系统管理员连接,普通用户无法连接。 数据库系统中会有多个数据库,但是同一时刻客户端程序只能连接一个数据库。当前,不支持在不同的数据库之间进行相互查询(跨库查询或跨库事务)。 当一个数据库集群中存在多个数据库时,可以通过客户端工具的-d参数指定目标数据库进行登录,也可以在客户端程序登录数据库以后通过\c命令进行数据库切换。
  • 注意事项 如果数据库的编码为SQL_ASCII(可以通过“show server_encoding”命令查看当前数据库存储编码),则在创建数据库对象时,如果对象名中含有多字节字符(例如中文),超过数据库对象名长度限制(63字节)的时候,数据库会将最后一个字节(而不是字符)截断,可能造成出现半个字符的情况。 针对这种情况,请遵循以下条件: 保证数据对象的名称不超过限定长度。 使用例如utf-8编码集做为数据库的默认存储编码集(server_encoding)。 不要使用多字节字符做为对象名。 如果出现因为误操作导致在多字节字符的中间截断而无法删除数据库对象的现象,请使用截断前的数据库对象名进行删除操作,或将该对象从各个数据库节点的相应系统表中依次删掉。
  • 行存表 默认创建表的类型。数据按行进行存储,即一行数据是连续存储。适用于对数据需要经常更新的场景。 123456789 openGauss=# CREATE TABLE customer_t1( state_ID CHAR(2), state_NAME VARCHAR2(40), area_ID NUMBER);--删除表openGauss=# DROP TABLE customer_t1;
  • 列存表 数据按列进行存储,即一列所有数据是连续存储的。单列查询IO小,比行存表占用更少的存储空间。适合数据批量插入、更新较少和以查询为主统计分析类的场景。列存表不适合点查询。 1 2 3 4 5 6 7 8 910 openGauss=# CREATE TABLE customer_t2( state_ID CHAR(2), state_NAME VARCHAR2(40), area_ID NUMBER)WITH (ORIENTATION = COLUMN);--删除表openGauss=# DROP TABLE customer_t2;
  • 创建表 执行如下命令创建表。 123456789 openGauss=# CREATE TABLE customer_t1( c_customer_sk integer, c_customer_id char(5), c_first_name char(6), c_last_name char(8))with (orientation = column,compression=middle)distribute by hash (c_last_name); 当结果显示为如下信息,则表示创建成功。 1 CREATE TABLE 其中c_customer_sk 、c_customer_id、c_first_name和c_last_name是表的字段名,integer、char(5)、char(6)和char(8)分别是这四个字段名称的类型。
  • 连接性能问题 开启了log_hostname,但是配置了错误的DNS导致的连接性能问题。 在连接上数据库,通过“show log_hostname”语句,检查数据库中是否开启了log_hostname参数。 如果开启了相关参数,那么数据库内核会通过DNS反查客户端所在机器的主机名。这时如果数据库CN所在的主机配置了不正确的/不可达的DNS服务器,那么会导致数据库建立连接过程较慢。 数据库内核执行初始化语句较慢导致的性能问题。 此种情况定位较难,可以尝试使用Linux的跟踪命令:strace。 strace gsql -U MyUserName -d postgres -h 127.0.0.1 -p 23508 -r -c '\q'Password for MyUserName: 此时便会在屏幕上打印出数据库的连接过程。比如较长时间停留在下面的操作上: sendto(3, "Q\0\0\0\25SELECT VERSION()\0", 22, MSG_NOSIGNAL, NULL, 0) = 22poll([{fd=3, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=3, revents=POLLIN}]) 此时便可以确定是数据库执行"SELECT VERSION()"语句较慢。 在连接上数据库后,便可以通过执行“explain performance select version()”语句来确定初始化语句执行较慢的原因。 另外还有一种场景不太常见:由于数据库CN所在机器的磁盘满或故障,此时所查询等受影响,无法进行用户认证,导致连接过程挂起,表现为假死。解决此问题联系客服人员清理数据库CN的数据盘空间便可。 TCP连接创建较慢问题。 此问题可以参考上面的初始化语句较慢排查的做法,通过strace跟踪,如果长时间停留在: connect(3, {sa_family=AF_FILE, path="/home/test/tmp/gaussdb_llt1/.s.PGSQL.61052"}, 110) = 0 或者 connect(3, {sa_family=AF_INET, sin_port=htons(61052), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) 那么说明客户端与数据库端建立物理连接过慢,此时应当检查网络是否存在不稳定、网络吞吐量太大的问题。
  • 其他故障 出现因“总线错误”(Bus error)导致的core dump或异常退出 一般情况下出现此种问题,是进程运行过程中加载的共享动态库(在Linux为.so文件)出现变化;或者进程二进制文件本身出现变化,导致操作系统加载机器的执行码或者加载依赖库的入口发生变化,操作系统出于保护目的将进程杀死,产生core dump文件。 解决此问题,重试便可。同时请尽可能避免在升级等运维操作过程中,在集群内部运行业务程序,避免升级时因替换文件产生此问题。 此故障的core dump文件的可能堆栈是dl_main及其子调用,它是操作系统用来初始化进程做共享动态库加载的。如果进程已经初始化,但是共享动态库还未加载完成,严格意义上来说,进程并未完全启动。
  • 创建连接故障 gsql: could not connect to server: No route to host 此问题一般是指定了不可达的地址或者端口导致的。请检查-h参数与-p参数是否添加正确。 gsql: FATAL: Invalid username/password,login denied. 此问题一般是输入了错误的用户名和密码导致的,请联系数据库管理员,确认用户名和密码的正确性。 The "libpq.so" loaded mismatch the version of gsql, please check it. 此问题是由于环境中使用的libpq.so的版本与gsql的版本不匹配导致的,请通过“ldd gsql”命令确认当前加载的libpq.so的版本,并通过修改LD_LIBRARY_PATH环境变量来加载正确的libpq.so。 gsql: symbol lookup error: xxx/gsql: undefined symbol: libpqVersionString 此问题是由于环境中使用的libpq.so的版本与gsql的版本不匹配导致的(也有可能是环境中存在PostgreSQL的libpq.so),请通过“ldd gsql”命令确认当前加载的libpq.so的版本,并通过修改LD_LIBRARY_PATH环境变量来加载正确的libpq.so。 gsql: connect to server failed: Connection timed out Is the server running on host "xx.xxx.xxx.xxx" and accepting TCP/IP connections on port xxxx? 此问题是由于网络连接故障造成。请检查客户端与数据库服务器间的网络连接。如果发现从客户端无法PING到数据库服务器端,则说明网络连接出现故障。请联系网络管理人员排查解决。 ping -c 4 10.10.10.1PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data.From 10.10.10.1: icmp_seq=2 Destination Host UnreachableFrom 10.10.10.1 icmp_seq=2 Destination Host UnreachableFrom 10.10.10.1 icmp_seq=3 Destination Host UnreachableFrom 10.10.10.1 icmp_seq=4 Destination Host Unreachable--- 10.10.10.1 ping statistics ---4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 2999ms gsql: FATAL: permission denied for database "postgres" DETAIL: User does not have CONNECT privilege. 此问题是由于用户不具备访问该数据库的权限,可以使用如下方法解决。 使用管理员用户连接数据库。 赋予该用户访问数据库的权限。 GRANT CONNECT ON DATABASE postgres TO user1; 实际上,常见的许多错误操作也可能产生用户无法连接上数据库的现象。如用户连接的数据库不存在,用户名或密码输入错误等。这些错误操作在客户端工具也有相应的提示信息。 gsql: FATAL: sorry, too many clients already,active/non-active: 197/3. 此问题是由于系统连接数量超过了最大连接数量。请联系数据库DBA进行会话连接数管理,释放无用会话。 关于查看用户会话连接数的方法如表1。 会话状态可以在视图PG_STAT_ACTIVITY中查看。无用会话可以使用函数pg_terminate_backend进行释放。 select datid,pid,state from pg_stat_activity; datid | pid | state -------+-----------------+-------- 13205 | 139834762094352 | active 13205 | 139834759993104 | idle(2 rows) 其中pid的值即为该会话的线程ID。根据线程ID结束会话。 SELECT PG_TERMINATE_BACKEND(139834759993104); 显示类似如下信息,表示结束会话成功。 PG_TERMINATE_BACKEND---------------------- t(1 row) 表1 查看会话连接数 描述 命令 查看指定用户的会话连接数上限。 执行如下命令查看连接到指定用户USER1的会话连接数上限。其中-1表示没有对用户user1设置连接数的限制。 SELECT ROLNAME,ROLCONNLIMIT FROM PG_ROLES WHERE ROLNAME='user1'; rolname | rolconnlimit---------+-------------- user1 | -1(1 row) 查看指定用户已使用的会话连接数。 执行如下命令查看指定用户USER1已使用的会话连接数。其中,1表示USER1已使用的会话连接数。 SELECT COUNT(*) FROM dv_sessions WHERE USERNAME='user1'; count------- 1(1 row) 查看指定数据库的会话连接数上限。 执行如下命令查看连接到指定数据库postgres的会话连接数上限。其中-1表示没有对数据库postgres设置连接数的限制。 SELECT DATNAME,DATCONNLIMIT FROM PG_DATABASE WHERE DATNAME='postgres'; datname | datconnlimit----------+-------------- postgres | -1(1 row) 查看指定数据库已使用的会话连接数。 执行如下命令查看指定数据库postgres上已使用的会话连接数。其中,1表示数据库postgres上已使用的会话连接数。 SELECT COUNT(*) FROM PG_STAT_ACTIVITY WHERE DATNAME='postgres'; count ------- 1(1 row) 查看所有用户已使用会话连接数。 执行如下命令查看所有用户已使用的会话连接数。 SELECT COUNT(*) FROM dv_sessions; count------- 10(1 row) gsql: wait xxx.xxx.xxx.xxx:xxxx timeout expired gsql在向数据库发起连接的时候,会有5分钟超时机制,如果在这个超时时间内,数据库未能正常的对客户端请求进行校验和身份认证,那么gsql会退出当前会话的连接过程,并报出如上错误。 一般来说,此问题是由于连接时使用的-h参数及-p参数指定的连接主机及端口有误(即错误信息中的xxx部分),导致通信故障;极少数情况是网络故障导致。要排除此问题,请检查数据库的主机名及端口是否正确。
  • 事务管理 在事务管理上,GaussDB采取了MVCC(多版本并发控制)结合两阶段锁的方式,其特点是读写之间不阻塞。GaussDB的MVCC没有将历史版本数据统一存放,而是和当前元组的版本放在了一起。GaussDB没有回滚段的概念,但是为了定期清除历史版本数据GaussDB引入了一个VACUUM线程。一般情况下,除非用户要做性能调优,否则不用特别关注VACUUM线程。此外,GaussDB对于单语句查询(没有使用begin等语句显示启动事务块)是自动提交事务的。
  • 连接数据库 连接数据库的客户端工具包括DAS、gsql和应用程序接口(如ODBC和JDBC)。 通过华为云数据管理服务(Data Admin Service,简称DAS)这款可视化的专业数据库管理工具,可获得执行SQL、高级数据库管理、智能化运维等功能,做到易用、安全、智能的管理数据库。GaussDB默认开通DAS连接权限。推荐使用DAS连接实例。连接GaussDB的具体操作请参考《DAS用户指南》。 gsql是GaussDB自带的客户端工具。使用gsql连接数据库,可以交互式地输入、编辑、执行SQL语句。具体连接方式请参考实例连接方式介绍。 用户可以使用标准的数据库应用程序接口(如ODBC和JDBC),开发基于GaussDB的应用程序。 分布式场景下:客户端工具通过连接CN访问数据库。因此连接前,需获取CN所在服务器的IP地址及CN的端口号信息。客户端工具可以通过连接任何一个CN访问数据库。正常业务使用禁止直接连接DN访问数据库。 主备版场景下:客户端工具通过连接主DN访问数据库。因此连接前,需获取主DN所在服务器的IP地址及端口号信息。正常业务使用禁止直接连接其他DN访问数据库。 应用程序接口 父主题: 数据库使用
  • 获取驱动包 根据不同版本的实例,下载不同版本的发布包,如表1所示。 表1 驱动包下载列表 版本 下载地址 3.x 驱动包 驱动包校验包 2.x 驱动包 驱动包校验包 为了防止软件包在传递过程或存储期间被恶意篡改,下载软件包时需下载对应的校验包对软件包进行校验,校验方法如下: 上传软件包和软件包校验包到虚拟机(Linux操作系统)的同一目录下。 执行如下命令,校验软件包完整性。 cat GaussDB_driver.zip.sha256 | sha256sum --check 如果回显OK,则校验通过。 GaussDB_driver.zip: OK
共100000条