华为云用户手册

  • 分析过程 GUC参数comm_max_stream表示任意两个DN之间stream的最大数量。 在CN上查询当前任意两个DN之间stream情况: 1 SELECT node_name,remote_name,count(*) FROM pgxc_comm_send_stream group by 1,2 order by 3 desc limit 100; 在DN上查询当前DN与其他DN之间stream情况: 1 SELECT node_name,remote_name,count(*) FROM pg_comm_send_stream group by 1,2 order by 3 desc limit 100; comm_max_stream参数值必须大于并发数*每并发平均stream算子数*(smp的平方)。 该参数默认值为:通过公式min(query_dop_limit * query_dop_limit * 2 * 20, max_process_memory(字节) * 0.025 /(最大CN数+当前DN数) / 260)计算,小于1024按照1024取值,其中query_dop_limit = 单个机器CPU核数 / 单个机器DN数。 不建议该参数值设置过大,因为comm_max_stream会占用内存(占用内存=256byte*comm_max_stream*comm_max_datanode),如果并发数据流数过大,查询较为复杂及smp过大都会导致内存不足。 如果comm_max_datanode参数值较小,进程内存充足,可以适当将comm_max_stream值调大。
  • 排查方法 查看相关表CU中数据分布情况,以下操作在DN执行。 查看列存表对应的cudesc表 针对非分区表: 1 SELECT 'cstore.'||relname FROM pg_class where oid = (SELECT relcudescrelid FROM pg_class c inner join pg_namespace n on c.relnamespace = n.oid where relname = 'table name' and nspname = 'schema name'); 针对分区表: 1 SELECT 'cstore.'||relname FROM pg_class where oid in (SELECT p.relcudescrelid FROM pg_partition p,pg_class c,pg_namespace n where c.relnamespace = n.oid and p.parentid = c.oid and c.relname = 'table name' and n.nspname = 'schema name' and p.relcudescrelid != 0); 查看cudesc中各CU的rowcount情况 查询步骤一返回的cudesc表信息,查询结果类似如下,主要关注row_count过小(远小于6w)的CU数量,如果此数量较大,说明当前小CU多,CU膨胀问题严重,影响存储效率和查询访问效率。
  • 处理方法 要删除的用户为一个数据库的owner,需要将对象的所有权重新分配给其他用户。有以下两种处理方法: 方式一:将数据库owner转移给其他用户。例如,使用ALTER语句将数据库testdb的owner用户u1修改为u2。 1 2 3 4 5 6 7 8 testdb=# ALTER DATABASE testdb OWNER to u2; ALTER DATABASE testdb=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+------------------------- testdb | u2 | UTF8 | en_US.UTF-8 | en_US.UTF-8 | (4 rows) 执行删除u1用户的命令,不再提示“owner of database testdb”的信息。 1 2 3 testdb=# DROP USER u1; ERROR: role "u1" cannot be dropped because some objects depend on it DETAIL: 3 objects in database gaussdb 方式二:如果已确认不需要数据库testdb,也可直接将其删除。将所有u1拥有的数据库对象的属主更改为u2。 1 2 testdb=# REASSIGN OWNED BY u1 TO u2; REASSIGN OWNED 清理owner是u1的对象。请谨慎使用,会将用户同名的schema也一同清理掉。 1 2 testdb=# DROP OWNED by u1; DROP OWNED 要删除的用户存在依赖关系,需要解除依赖关系。处理方法如下: 识别依赖关系。根据报错信息“3 objects in database gaussdb”可知gaussdb数据库里有3个对象依赖u1。由于数据库内系统表的依赖,在其他数据库中不会打印出详细的依赖对象信息,那么在gaussdb库中执行DROP USER的时候,会打印出具体的信息。 连接到gaussdb库执行如下命令: 1 2 3 4 gaussdb=# DROP USER u1; ERROR: role "u1" cannot be dropped because some objects depend on it DETAIL: privileges for table pg_class privileges for schema u2 获取到依赖项的详细信息如下: privileges for table pg_class:pg_class上u1用户的权限。 schema u2上u1用户的权限。 撤销依赖对象的权限。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 gaussdb=# SELECT relname,relacl FROM pg_class WHERE relname = 'pg_class'; relname | relacl ----------+---------------------------------- pg_class | {=r/Ruby,u1=r/Ruby} (1 row) gaussdb=#SELECT nspname,nspacl FROM pg_namespace WHERE nspname = 'u2'; nspname | nspacl ---------+----------------------------- u2 | {u2=UC/u2,u2=LP/u2,u1=U/u2} gaussdb=# REVOKE SELECT ON TABLE pg_class FROM u1; REVOKE gaussdb=# REVOKE USAGE ON SCHEMA u2 FROM u1; REVOKE 再删除用户,可成功删除,不再提示有依赖。 1 2 gaussdb=# DROP USER u1; DROP USER
  • 问题现象 数据库使用中遇到某些用户离职或者角色变更时,要对其账号进行销户、权限进行回收等操作,但是删除用户时出现类似:role “u1” cannot be dropped because some objects depend on it的报错信息,无法删除该用户。 例如,要删除用户u1时,出现如下提示: 1 2 3 4 testdb=# DROP USER u1; ERROR: role "u1" cannot be dropped because some objects depend on it DETAIL: owner of database testdb 3 objects in database gaussdb
  • 解决方案 方案一:设置参数behavior_compat_options为merge_update_multi。 当目标表匹配到多行满足条件时,该方案不会报错,而是会随机匹配一行数据,有数据遗漏风险。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SET behavior_compat_options=merge_update_multi; MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id = 1502; MERGE 1 SELECT * FROM products ; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | play gym | toys (3 rows) 方案二:修改MERGE INTO匹配条件。 尽可能选择筛选结果唯一的表达式为匹配条件。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id != 1502; MERGE 1 SELECT * FROM products; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | lamaze | toys (3 rows)
  • 问题现象 执行MERGE INTO将源表内容根据匹配条件对目标表做更新报错unable to get a stable set of rows in the source table。 现有目标表products和源表newproducts,以源表newproducts中product_id为1502为匹配条件,对目标表进行更新报错: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 CREATE TABLE products (product_id INTEGER,product_name VARCHAR2(60),category VARCHAR2(60)); INSERT INTO products VALUES (1501, 'vivitar 35mm', 'electrncs'),(1502, 'olympus is50', 'electrncs'),(1600, 'play gym', 'toys'); CREATE TABLE newproducts (product_id INTEGER,product_name VARCHAR2(60),category VARCHAR2(60)); INSERT INTO newproducts VALUES (1502, 'olympus camera', 'electrncs'),(1600, 'lamaze', 'toys'),(1502, 'skateboard', 'toy'); MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id = 1502; ERROR: dn_6003_6004: unable to get a stable set of rows in the source tables
  • 原因分析 源表newproducts中product_id为1502的数据有两条,且参数behavior_compat_options缺省,因此MERGE INTO时匹配到多条数据报错。 MERGE INTO的作用是将源表内容根据匹配条件对目标表做更新或插入,当目标表匹配到多行满足条件时, GaussDB (DWS)有以下两种行为: 业务报错:unable to get a stable set of rows in the source table。 随机匹配一行数据,可能会导致实际与预期不符。 这两种行为由参数behavior_compat_options控制,当参数behavior_compat_options缺省的情况下,匹配到多行会报错,如果behavior_compat_options被设置为merge_update_multi,则不会报错,而是会随机匹配一行数据。 因此,当出现merge into的结果与预期不符的情况时,需查看该参数是否被设置,同时排查是否匹配了多行数据,并根据实际情况修改业务逻辑。
  • 处理方法 场景一:语句估算内存过大,造成排队。 查询pg_session_wlmstat视图,查看状态为running的语句是否个数很少,而且statement_mem字段数值是否较大(单位为MB,一般认为大于max_dynamic_memory 1/3即为大内存语句)。如果都符合就可以判断是此类语句占据内存导致整体运行缓慢。 1 SELECT usename,substr(query,0,20),threadid,status,statement_mem FROM pg_session_wlmstat where usename not in ('omm','Ruby') order by statement_mem,status desc; 如上图所示,只有最后一个语句是running状态,其余语句都是pending状态。根据statement_mem可以看到该语句占据2576MB内存。此时根据语句的threadid,执行以下命令终止对应的查询语句,终止后即可释放资源,其余语句正常运行。 1 SELECT pg_terminate_backend(threadid); 场景二:所有语句状态都是pending状态,没有运行的语句。此时应是管控机制出现异常,直接终止所有线程,即可恢复正常。 1 SELECT pg_terminate_backend(pid) FROM pg_stat_activity where usename not in ('dbadmin','Ruby');
  • 处理方法 删除该表索引信息。 1 DROP INDEX a_0317_index; 对该表索引进行重建。 1 CREATE INDEX a_0317_index on a_0317(a) local (partition p1_index, partition p2_inde); 查看表定义无报错。 1 2 3 4 5 6 7 8 9 10 11 12 13 \d+ a_0317 Table "public.a_0317" Column | Type | Modifiers | Storage | Stats target | Description --------+---------+-----------+---------+--------------+------------- a | integer | | plain | | Indexes: "a_0317_index" btree (a) LOCAL(PARTITION p1_index, PARTITION p2_inde) TABLESPACE pg_default Range partition by(a) Number of partition: 2 (View pg_partition to check each partition range.) Has OIDs: no Distribute By: HASH(a) Location Nodes: ALL DATANODES Options: orientation=row, compression=no
  • 问题复现 创建分区表a_0317,含p1,p2两个分区。 1 CREATE TABLE a_0317(a int) partition by range(a) (partition p1 values less than (4), partition p2 values less than (8)); 创建主表与分区索引。 1 CREATE INDEX a_0317_index on a_0317(a) local (partition p1_index, partition p2_inde); 查看分区表分区索引信息如下: 查看主表索引信息。 1 2 3 4 5 6 7 8 9 10 11 SELECT oid,* FROM pg_class where relname ='a_0317_index'; oid | relname | relnamespace | reltype | reloftype | relowner | relam | relfilenode | reltablespace | relpages | reltuples | relallvisible | reltoastrelid | reltoastidxid | reldeltarelid | reld eltaidx | relcudescrelid | relcudescidx | relhasindex | relisshared | relpersistence | relkind | relnatts | relchecks | relhasoids | relhaspkey | relhasrules | relhastriggers | relhassubclass | relcmprs | relhasclusterkey | relrowmovement | parttype | relfrozenxid | relacl | reloptions | relreplident | relfrozenxid64 --------+--------------+--------------+---------+-----------+----------+-------+-------------+---------------+----------+-----------+---------------+---------------+---------------+---------------+----- --------+----------------+--------------+-------------+-------------+----------------+---------+----------+-----------+------------+------------+-------------+----------------+----------------+--------- -+------------------+----------------+----------+--------------+--------+------------+--------------+---------------- 241487 | a_0317_index | 2200 | 0 | 0 | 16393 | 403 | 241487 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | f | f | p | i | 1 | 0 | f | f | f | f | f | 0 | f | f | p | 0 | | | n | 0 (1 row) 根据主表索引信息查看分区索引信息。 1 2 3 4 5 6 7 8 9 10 SELECT * FROM pg_partition where parentid= 241487; relname | parttype | parentid | rangenum | intervalnum | partstrategy | relfilenode | reltablespace | relpages | reltuples | relallvisible | reltoastrelid | reltoastidxid | indextblid | indisusable | reldeltarelid | reldeltaidx | relcudescrelid | relcudescidx | relfrozenxid | intspnum | partkey | intervaltablespace | interval | boundaries | transit | reloptions | relfrozenxid64 ----------+----------+----------+----------+-------------+--------------+-------------+---------------+----------+-----------+---------------+---------------+---------------+------------+-------------+- --------------+-------------+----------------+--------------+--------------+----------+---------+--------------------+----------+------------+---------+------------+---------------- p1_index | x | 241487 | 0 | 0 | n | 241488 | 0 | 0 | 0 | 0 | 0 | 0 | 241485 | t | 0 | 0 | 0 | 0 | 0 | | | | | | | | 0 p2_inde | x | 241487 | 0 | 0 | n | 241489 | 0 | 0 | 0 | 0 | 0 | 0 | 241486 | t | 0 | 0 | 0 | 0 | 0 | | | | | | | | 0 (2 rows) 连接CN开启读写事务,从pg_partition系统表删除p1分区的索引信息。 1 2 START TRANSACTION read write; DELETE from pg_partition where relname = 'p1_index'; 查看表定义报错与现场报错相同,问题复现: 1 2 \d+ a_0317 ERROR: The local index 700633 on the partition 700647 not exist.CONTEXT: referenced column: pg_get_indexdef
  • 处理方法 这两种行为由参数behavior_compat_options控制,当参数behavior_compat_options缺省的情况下,匹配到多行会报错,如果behavior_compat_options设置了merge_update_multi参数项,这种情况下不会报错,而是会随机匹配一行数据。 因此,当出现MERGE INTO的结果与预期不符时,需查看该参数是否被设置,同时排查是否匹配了多行数据,并修改业务逻辑。
  • 问题现象 场景一:执行VACUUM FULL时报错“Can't fit xid into page, now xid is 34181619720, base is 29832807366, min is 3, max is 3.”。 场景二:其他非VACUUM FULL操作,例如业务场景中给用户赋予函数的操作权限时,报错信息“Can't fit xid into page. relation "pg_proc", now xid is 34181619720, base is 29832807366, min is 3, max is 3.”。
  • 问题现象 DWS中有两种情况需要关注表是否做过UPDATE及DELETE操作: 对表频繁执行UPDATE或者DELETE操作会产生大量的磁盘页面碎片,从而逐渐降低查询的效率,需要将磁盘页面碎片恢复并交还操作系统,即VACUUM FULL操作,这种场景下需要查找出哪些表执行过UPDATE; 判断一张表是否是维度表,是否可以从Hash表变更为复制表,可以查看这张表是否执行过UPDATE或DELETE,如果执行过UPDATE或DELETE操作,则不能修改为复制表。
  • 处理方法 通过以下命令查找哪些表执行过UPDATE及DELETE操作: 1 2 3 4 5 6 7 8 9 ANALYZE tablename; SELECT n.nspname , c.relname, pg_stat_get_tuples_deleted(x.pcrelid) as deleted, pg_stat_get_tuples_updated(x.pcrelid) as updated FROM pg_class c INNER JOIN pg_namespace n ON n.oid = c.relnamespace INNER JOIN pgxc_class x ON x.pcrelid = c.oid WHERE c.relkind = 'r' and c.relname='tablename' ;
  • 处理方法 通过Function的exception方式屏蔽该报错,将大小统一到一个值,对于不存在的表,可以用大小为-1来表示,函数如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 CREATE OR REPLACE FUNCTION public.pg_t_size(tab_oid OID,OUT retrun_code text) RETURNS text LANGUAGE plpgsql AS $$ DECLARE v_sql text; ts text; BEGIN V_SQL:='select pg_size_pretty(pg_table_size('||tab_oid||'))'; EXECUTE IMMEDIATE V_SQL into ts; IF ts IS NULL THEN RETRUN_CODE:=-1; ELSE return ts; END IF; EXCEPTION WHEN OTHERS THEN RETRUN_CODE:=-1; END$$; 执行如下命令查询结果: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 call public.pg_t_size('1',''); retrun_code ------------- -1 (1 row) select oid from pg_class limit 2; oid ------ 2662 2659 (2 rows) call public.pg_t_size('2662',''); retrun_code ------------- 120 KB (1 row)
  • 原因分析 上述问题中撤销user3对表t1的访问权限未生效是因为:之前执行过GRANT SELECT ON table t1 TO public;这条SQL语句,该语句中关键字public表示该权限要赋予给所有角色,包括之后新创建的角色,所以新用户user3对该表也有访问权限。public可以看做是一个隐含定义好的组,它包含所有角色。 因此,执行完REVOKE SELECT ON table t1 FROM user3;之后,虽然user3用户没有了表t1的访问权限(通过系统表pg_class的relacl字段可查看t1表的权限),但是他仍然有public的权限,所以仍能访问该表。
  • 处理方法 使用GRANT语法对表/schema进行赋权,示例: 假设当前有两个用户tom和jerry,如果想要用户jerry能够对当前tom创建的所有表以及将来创建的表都有查询权限,如何处理: 将用户tom下的同名schema权限赋给jerry。 1 GRANT USAGE ON SCHEMA tom TO jerry; 将用户tom已经创建的表的select权限赋给jerry。 1 GRANT SELECT ON ALL TABLES IN SCHEMA tom TO jerry; 将用户tom未来在同名schema下创建的表的select权限赋给jerry。 1 ALTER DEFAULT PRIVILEGES FOR USER tom IN SCHEMA tom GRANT SELECT ON TABLES TO jerry;
  • 处理方法 String_agg中增加order by,语句修改为如下格式保证ename字段是按照相同的顺序来拼接的,从而满足查询结果是稳定的。 1 2 3 4 select count(*) from (select deptno, string_agg(ename, ',' order by ename desc) from employee group by deptno) t1 , (select deptno, string_agg(ename, ',' order by ename desc) from employee group by deptno) t2 where t1.string_agg = t2.string_agg;
  • 原因分析 某业务场景中的SQL语句中使用了string_agg函数,语句逻辑如下: 执行如下SQL语句: 1 2 3 4 select count(*) from (select deptno, string_agg(ename, ',') from employee group by deptno) t1 , (select deptno, string_agg(ename, ',') from employee group by deptno) t2 where t1.string_agg = t2.string_agg;
  • 处理方法 可登录GaussDB(DWS)管理控制台,设置session_timeout为0或预期时长,使会话保持长时间连接。 登录GaussDB(DWS)管理控制台。在集群列表中找到所需要的集群,单击集群名称,进入“集群详情”页面。 单击“参数修改”页签,修改session_timeout参数值,然后单击“保存”。 COPY导入执行完成后,建议继续设置session_timeout=10min,因为如果有客户端长时间连接数据库,但对数据库不进行任何操作,该连接将一直占用一个线程,如果这样的客户端连接很多,就会出现大量的线程都被空闲的连接占用,从而导致数据库连接满或者资源浪费。
  • 问题现象 通过JDBC连接集群执行COPY导入时报错: org.postgresql.util.PSQLException: Database connection failed when starting copy at org.postgresql.core.v3.QueryExecutorImpl.startCopy(QueryExecutorImpl.java:804) at org.postgresql.copy.CopyManager.copyIn(CopyManager.java:52) at org.postgresql.copy.CopyManager.copyIn(CopyManager.java:161) at org.postgresql.copy.CopyManager.copyIn(CopyManager.java:146) at copy.main(copy.java:95) Caused by: java.io.EOFExceptionat org.postgresql.core.PGStream.ReceiveChar(PGStream.java:284) at org.postgresql.core.v3.QueryExecutorImpl.processCopyResults(QueryExecutorImpl.java:1008) at org.postgresql.core.v3.QueryExecutorImpl.startCopy(QueryExecutorImpl.java:802) ... 4 more
  • 处理方法 数据库的兼容模式在CREATE DATABASE时由DBCOMPATIBILITY参数指定。 DBCOMPATIBILITY [ = ] compatibility_type 指定兼容的数据库的类型。 取值范围:ORA、TD、MySQL。分别表示兼容Oracle、Teradata和MySQL数据库。 若创建数据库时不指定该参数,默认为ORA。 为解决DATABASE的兼容性模式问题,需要将两个数据库的兼容模式修改为一致。GaussDB(DWS)不支持ALTER方式修改已有数据库的兼容模式DBCOMPATIBILITY,只能通过新建数据库的方式来指定兼容模式。 1 2 CREATE DATABASE td_db DBCOMPATIBILITY ='TD'; CREATE DATABASE GaussDB(DWS)不同兼容模式下Oracle、Teradata和MySQL语法行为会有一些差异,具体的差异内容可参考Oracle、Teradata和MySQL语法兼容性差异。
  • 原因分析 GaussDB(DWS)支持Oracle、Teradata和MySQL数据库兼容模式。 在TD/MySQL兼容模式下,空和NULL是不相等的,在ORA兼容模式下,空和NULL是相等的。因此上述场景可能是因为两个环境中数据库的兼容性模式设置不一致导致。 可通过查询PG_DATABASE系统表确认数据库的兼容模式: 1 SELECT datname, datcompatibility FROM pg_database;
  • 分析过程 和用户确认是部分业务慢,获取部分慢SQL后,打印执行计划,分析出耗时主要在index scan上,可能是IO争抢导致,通过监控IO,发现并没有IO资源使用瓶颈。 查询当前活跃SQL,发现有大量的CREATE INDEX语句,需要和用户确认该业务是否合理。 1 SELECT * from pg_stat_activity where state !='idle' and usename !='Ruby'; 根据执行计划,发现在部分DN上耗时较高,查询表的倾斜情况,并未发现有倾斜的情况。 1 SELECT table_skewness('table name'); 联系运维人员登录集群实例,检查内存相关参数,设置不合理,需要优化。 单节点总内存大小为256GB。 max_process_memory为12GB,设置过小。 shared_buffers为32MB,设置过小。 work_mem:CN:64MB 、DN:64MB。 max_active_statements为-1(不限制并发数)。 按以下值设置: gs_guc set -Z coordinator -Z datanode -N all -I all -c "max_process_memory=25GB" gs_guc set -Z coordinator -Z datanode -N all -I all -c "shared_buffers=8GB" gs_guc set -Z coordinator -Z datanode -N all -I all -c "work_mem=128MB" 进一步分析扫描慢的原因,发现表数据膨胀严重,对其中一张8GB大小的表,总数据量5万条,做完VACUUM FULL后大小减小为5.6MB。
  • 分析过程 排查当前的IO、内存、CPU使用情况,没有发现资源占用高的情况。 查看慢SQL的线程等待状态。 根据线程等待状态,并没有出现都在等待某个DN的情况,初步排除中间结果集偏斜到了同一个DN的情况。 1 SELECT * FROM pg_thread_wait_status WHERE query_id='149181737656737395'; 联系运维人员登录到相应的实例节点上,打印等待状态为none的线程堆栈信息如下。 通过反复打印堆栈信息,发现堆栈在变化,并没有hang死,所以初步判断该问题为性能慢的问题。另堆栈中有VecNestLoopRuntime,结合执行计划,初步判断是由于统计信息不准,优化器评估结果集较少,执行计划使用了NestLoop导致性能下降。 gstack 14104 对表执行ANALYZE后性能并没有太大改善。 对SQL增加hint关闭索引,让优化器强行使用hashjoin,发现hint功能没有生效,原因是hint无法改变子查询中的计划。 通过SET enable_indexscan = off,执行计划被改变,使用了Hash Left Join,慢SQL在3秒左右返回结果,查询性能恢复。
  • 分析过程 和用户确认部分业务慢,执行慢的业务中都涉及到了同一张表tb_motor_vehicle。 收集几个典型的慢SQL语句,分别打印执行计划。从执行计划中可以看出来,两条SQL的耗时都集中在Partitioned CS tore Scan on public.tb_motor_vehicle列存表的分区扫描上。 已确认该表的分区键为createtime,而涉及的SQL中无任何createtime的筛选和过滤条件,基本可以确认是由于慢SQL的计划没有走分区剪枝,导致了全表扫描,对于185亿条数据量的表,全表扫描性能会很差。
  • 处理方法 审视用户自定义函数的provolatile属性是否定义正确。如果定义不正确,要修改对应的属性,使它能够下推执行。 具体判断方法可以参考如下说明: 函数相关的所有属性都在pg_proc系统表中可以查到,与函数能否下推相关的两个属性是provolatile和proshippable: 如果函数的provolatile属性为i,则无论proshippable的值是否为t,则函数始终可以下推。 如果函数的provolatile属性为s或v,则仅当proshippable的值为t时,函数可以下推。 provolatile的本质含义是描述函数的易变属性,取值为i/s/v。i代表IMMUTABLE,s代表STABLE,v代表VOLATILE。 例如: 如果一个函数对于同样的输入,一定有相同的输出,那么这类函数就是IMMUTABLE的。例如,绝大部分的字符串处理函数,这类函数始终可以下推。 如果一个函数的返回结果在一个SQL语句的调用过程中,结果是相同的,那么它就是STABLE的。例如,时间相关的处理函数,它的最终显示结果可能与具体的GUC参数相关(例如控制时间显示格式的参数),这类函数都是STABLE的,此类函数仅当其属性是SHIPPABLE的时候,才能下推。 如果一个函数的返回结果可能随着每一次的调用而返回不同的结果。例如,nextval、random这种函数,每次调用结果都是不可预期的,这类函数就是VOLATILE的,此类函数仅当其属性是SHIPPABLE的时候,才能下推。 proshippable字段表示函数是否可以下推到DN上执行,默认值是false,取值范围为t/f/NULL。
  • 原因分析 GaussDB(DWS)支持Hash、REPLICATION和ROUNDROBIN(8.1.2集群及以上版本支持ROUNDROBIN)分布方式。如果创建了Hash分布的表,未指定分布键,则选择表的第一列作为分布键,这种情况就可能存在倾斜。倾斜造成以下负面影响: SQL的性能会非常差,因为数据只分布在部分DN,那么SQL运行的时候就只有部分DN参与计算,没有发挥分布式的优势。 会导致资源倾斜,尤其是磁盘。可能部分磁盘的空间已经接近极限,但是其他磁盘利用率很低。 可能出现部分节点CPU过高等问题。
  • 原因分析 业务数据文件从Oracle导入,文件编码为utf-8。该报错还会提示行数,由于文件特别大,vim命令打不开文件,于是用sed命令把报错行数提出来,再用vim命令打开,发现并没有什么异常。用split命令按行数切割后,部分文件也可以导入。 经分析GaussDB(DWS)的varchar型的字段或变量不允许含有'\0'(也即数值0x00、UTF编码'\u0000')的字符串 ,需在导入前去掉字符串中的'\0'。
  • 原因分析 MySQL5.0.3之前varchar(n)这里的n表示字节数。 MySQL5.0.3之后varchar(n)这里的n表示字符数,比如varchar(200),不管是英文还是中文都可以存放200个。 GaussDB(DWS)的varchar(n)这里的n表示字节数。 根据字符集,字符类型如果为gbk,每个字符占用2个字节;字符类型如果为utf8,每个字符最多占用3个字节。根据转换规则,同样的字段长度,会导致GaussDB(DWS)出现字段超长的问题。
共100000条