[GaussDB-] GaussDB分区表查询性能异常分析

问题现象

使用分区表进行相关查询业务,SQL性能慢。

原因分析

导致分区表业务慢的常见原因有以下几种:

  • 分区索引失效,顺序扫描导致的SQL性能慢
  • 分区表无法进行分区剪枝导致的SQL性能慢
  • SQL计划选择非最优导致的SQL性能慢

处理方法

判断是否存在索引异常的行为

部分分区DDL如果不带UPDATE GLOBAL INDEX子句,会导致分区表Global索引失效。同时用户也可以使用ALTER TABLE或者ALTER INDEX使分区表索引失效。当分区表或者部分分区上索引不可用后,会导致查询SQL无法走索引扫描,从而出现慢SQL场景。

  • 查询索引类型和状态

分区表的索引有两种,Local索引和Global索引。Local索引会在每个分区创建一个索引,Global索引会在整个分区表上创建一个全局索引。对于Local索引,需要确认整个索引自身状态和目标查询分区的索引状态;对于Global索引,只需要确认整个索引自身状态。
可以通过系统表pg_index查询分区表的所有索引,并获取索引是否可用的状态,其索引类型在pg_class中给出。下面给出了查询分区表t1的全部索引状态及索引类型的命令参考:

gaussdb=# select c.relname, i.indisusable, c.relkind from pg_class c join pg_index i on c.oid=i.indexrelid 
    join pg_class r on i.indrelid=r.oid where r.relname='t1'; 
      relname       | indisusable | relkind  
--------------------+-------------+--------- 
 t1_c1_idx          | t           | i 
 t1_c2_tableoid_idx | f           | I

其中indisusable字段为’t’表示该索引可用,为’f’表示索引已经失效,在查询业务中该索引无法使用;relkind为’i’表示该索引为Local索引,为’I’表示该索引为Global索引。
或者通过元语句\d命令查询分区表的索引信息:

gaussdb=# \d t1 
      Table "public.t1" 
 Column |  Type   | Modifiers  
--------+---------+----------- 
 c1     | integer |  
 c2     | integer |  
Indexes: 
    "t1_c1_idx" btree (c1) LOCAL TABLESPACE pg_default 
    "t1_c2_tableoid_idx" btree (c2) TABLESPACE pg_default UNUSABLE 
Partition By RANGE(c1) 
Number of partitions: 2 (View pg_partition to check each partition range.)

可以看到表t1的两条索引t1_c1_idx、t1_c2_tableoid_idx被列出。其中t1_c1_idx带有LOCAL关键字,表示该索引为Local索引,t1_c2_tableoid_idx没有LOCAL关键字,表示该索引为Global索引。同时t1_c2_tableoid_idx标记了UNUSABLE,表示该索引不可用。

  • 查询索引分区状态

对于Local索引,还需要确认目标查询分区的索引状态,这个信息可以从系统表pg_partition中查询。

gaussdb=# select p.relname,p.indisusable from pg_partition p join pg_class c on p.parentid=c.oid where c.relname='t1_c1_idx'; 
  relname  | indisusable  
-----------+------------- 
 p1_c1_idx | t 
 p2_c1_idx | f 
(2 rows)

可以看到索引分区p1_c1_idx可用,索引分区p2_c1_idx不可用。在分区p2上的查询无法使用索引t1_c1_idx。

  • 重建异常的索引/索引分区

如果分区表的索引/索引分区状态异常,会导致查询SQL无法走索引扫描,需要重建索引/索引分区。重建索引的命令如下:

ALTER INDEX t1_c2_tableoid_idx REBUILD;

重建索引分区的命令如下:

ALTER INDEX t1_c1_idx REBUILD PARTITION p2_c1_idx;

判断分区表是否存在剪枝异常的场景

当分区表的分区键所在列存在条件时,可以触发分区剪枝。数据库会在优化器/执行器阶段识别到需要扫描的分区,而不会扫描全部分区。只有分区表的业务是顺序扫描,或者使用Local索引进行扫描时候,才可能触发分区剪枝;Global索引不会触发分区剪枝,这是因为Global索引是在整个分区表上创建的单个索引,不存在剪枝的概念。
剪枝是被动触发的,当查询业务满足分区剪枝条件时,会自动触发分区剪枝。

  • 判断是否触发了分区剪枝

可以通过查询计划来判断是否触发了分区剪枝。当扫描分区数少于分区总数时,即触发了分区剪枝。分区剪枝分为静态剪枝和动态剪枝,静态剪枝是指在优化器阶段就能识别到裁剪的分区;动态剪枝是指优化器阶段只能确定可以进行剪枝,但不知道具体裁剪到哪个分区,在执行器阶段才会确定裁剪的目标分区。
下面的业务触发了分区静态剪枝,计划中的’Iterations: 1’表示扫描了1个分区,'Selected Partitions: 1’表示扫描的目标分区下标是1。
这个下标是一个逻辑数组下标,对于范围分区/间隔分区,按照分区定义上界值升序排列;对于列表分区,按照第一个枚举值升序排列;对于哈希分区,按照计算后的哈希值升序排列。可以通过函数pg_get_tabledef获取分区定义,其列出的分区即为该对应下标。

gaussdb=# explain select * from t1 where c1 < 100; 
                              QUERY PLAN                                
----------------------------------------------------------------------- 
 Partition Iterator  (cost=0.00..27.86 rows=716 width=8) 
   Iterations: 1 
   ->  Partitioned Seq Scan on t1  (cost=0.00..27.86 rows=716 width=8) 
         Filter: (c1 < 100) 
         Selected Partitions:  1 
(5 rows)

下面的业务没有触发分区剪枝,计划中的’Iterations: 2’表示扫描了2个分区,'Selected Partitions: 1…2’表示扫描的目标分区下标是1和2。可以看到扫描的分区数等于分区表的总分区数,表示未进行任何分区剪枝。

gaussdb=# explain select * from t1; 
                               QUERY PLAN                                
------------------------------------------------------------------------ 
 Partition Iterator  (cost=0.00..31.49 rows=2149 width=8) 
   Iterations: 2 
   ->  Partitioned Seq Scan on t1  (cost=0.00..31.49 rows=2149 width=8) 
         Selected Partitions:  1..2 
(4 rows)

下面的业务触发了分区动态剪枝,计划中的’Iterations: PART’和’Selected Partitions: PART’表示优化器识别到分区表可以进行分区剪枝,但具体

gaussdb=# prepare p1 as select * from t1 where c1 < $1; 
gaussdb=# explain execute p1(100); 
                                         QUERY PLAN                                          
-------------------------------------------------------------------------------------------- 
 Partition Iterator  (cost=9.80..28.75 rows=716 width=8) 
   Iterations: PART 
   ->  Partitioned Bitmap Heap Scan on t1  (cost=9.80..28.75 rows=716 width=8) 
         Recheck Cond: (c1 < $1) 
         Selected Partitions:  PART 
         ->  Partitioned Bitmap Index Scan on t1_c1_idx  (cost=0.00..9.62 rows=716 width=0) 
               Index Cond: (c1 < $1) 
               Selected Partitions:  PART 
(8 rows)
  • 支持分区剪枝的场景

当分区键所在列存在条件时,可以进行分区剪枝。条件剪枝支持场景为:比较表达式(<,<=,=,>=,>)、逻辑表达式(AND、OR)、数组表达式。需要注意的是,列表和哈希分区不支持除等号外的其他比较表达式的剪枝。如果条件全为常量,则进行静态剪枝;如果条件带有参数、部分隐式转换、immutable函数,则进行动态剪枝。
当分区表作为参数化路径计划的内表且分区键所在列为索引检索条件时,支持动态剪枝。

  • 不支持分区剪枝的场景

分区键所在列的条件为子查询表达式、无法直接强转的类型转换、stable/volatile函数时,不支持分区剪枝。
分区表在生成除参数化路径外的其他JOIN计划时,不支持动态剪枝。

  • 业务改写适配分区剪枝

当业务设计不合理,导致原本逻辑上可以走分区剪枝的计划,最终未走分区剪枝时,可以改写业务以适配分区剪枝,从而提升分区表查询业务性能。比如使用HINT固定计划、在客户端修改绑参类型等方法。

详情查看:https://doc.hcs.huawei.com/db/zh-cn/gaussdbqlh/24.1.30/productdesc/qlh_03_0001.html

<think>好的,用户现在问的是Gauss100 OLTP的语言特征。之前我们讨论过Oracle的索引并行度问题,可能用户现在在比较不同数据库的特性,或者考虑迁移到GaussDB。我需要先确认Gauss100 OLTP的具体信息,因为GaussDB有不同的版本,比如华为的GaussDB 100和200,可能用户指的是GaussDB 100 OLTP。 首先,用户可能想知道GaussDBSQL兼容性,是否支持标准SQL,有没有扩展功能。比如,Oracle有PL/SQL,而GaussDB可能使用自己的存储过程语言。需要查证GaussDB 100 OLTP是否支持存储过程,触发器,自定义函数等。 其次,用户可能关心事务处理能力,比如ACID支持,隔离级别,分布式事务等。GaussDB作为OLTP数据库,应该支持这些,但需要具体说明其语言特性如何实现这些事务控制,比如是否支持BEGIN TRANSACTION,COMMIT,ROLLBACK等语句。 另外,用户可能想了解高级功能,比如分区表、并行查询、索引类型等,这些在SQL语法中的体现。比如是否支持分区表的特定语法,或者有没有类似于Oracle的并行提示。 还要考虑用户的使用场景,可能是企业级应用,需要高并发和低延迟,所以GaussDBSQL执行优化方面的特性,比如执行计划管理,锁机制,以及如何通过SQL语句进行性能调优。 另外,用户可能对兼容性感兴趣,比如GaussDB是否兼容Oracle或PostgreSQL的语法,这样迁移现有应用会更方便。需要确认GaussDBSQL方言是否兼容常见数据库,是否有特定的扩展或修改。 可能还需要提到安全相关的语言特性,比如数据加密,权限控制相关的SQL语句,如GRANT,REVOKE,以及是否支持行级安全策略。 最后,用户可能需要知道GaussDB特有的功能,比如分布式架构下的SQL处理,如何跨节点执行查询,是否支持全局事务等。这些都会在SQL语句或存储过程中有所体现。 需要确保回答结构清晰,分点列出,涵盖SQL兼容性、事务支持、高级功能、分布式特性、安全机制等,并给出示例帮助用户理解。同时,注意对比用户之前的Oracle问题,指出可能的不同之处,帮助用户迁移或对比。</think>--- **Gauss100 OLTP(华为GaussDB OLTP版)** 是华为推出的面向事务处理的高性能关系型数据库,其语言特征基于 **SQL 标准** 并针对企业级场景进行了扩展优化。以下是其核心语言特性: --- ### **1. SQL 标准兼容性** - **ANSI SQL 兼容** 支持 SQL-92、SQL:1999 等核心标准语法,确保与主流数据库(如 Oracle、MySQL)的语法兼容性,降低迁移成本。 - **数据类型** 支持标准数值、字符串、日期、JSON、空间地理等类型,同时扩展了高性能存储类型(如 `UROWID`)。 --- ### **2. 事务处理能力** - **ACID 支持** 通过 `BEGIN TRANSACTION`、`COMMIT`、`ROLLBACK` 等语句实现严格的事务控制,支持 `READ COMMITTED`、`REPEATABLE READ` 等隔离级别。 - **分布式事务** 提供全局事务管理(如两阶段提交协议),支持跨节点的分布式事务一致性。 --- ### **3. 存储过程与编程扩展** - **PL/SQL 兼容语法** 支持存储过程、函数、触发器,语法与 Oracle PL/SQL 高度相似(需开启兼容模式),例如: ```sql CREATE OR REPLACE PROCEDURE update_salary (emp_id INT) AS BEGIN UPDATE employees SET salary = salary * 1.1 WHERE id = emp_id; END; ``` - **高级编程特性** 支持游标、异常处理、动态 SQL(`EXECUTE IMMEDIATE`),满足复杂业务逻辑需求。 --- ### **4. 分布式架构支持** - **分片语法** 支持通过 `DISTRIBUTE BY` 定义数据分布策略(如哈希、范围分片),例如: ```sql CREATE TABLE orders ( order_id INT, user_id INT ) DISTRIBUTE BY HASH(user_id); ``` - **全局视图与跨节点查询** 提供全局视图(`GLOBAL TEMPORARY TABLE`)和联邦查询能力,简化跨分片数据访问。 --- ### **5. 性能优化扩展** - **执行计划控制** 支持 `HINT` 指令优化查询计划(如 `/*+ INDEX(orders idx_order_id) */`)。 - **并行查询** 通过 `PARALLEL` 关键字启用多线程加速(如 `SELECT /*+ PARALLEL(8) */ * FROM large_table`)。 - **分区表** 支持范围、列表、哈希分区,语法与 Oracle 类似: ```sql CREATE TABLE sales ( sale_date DATE, region VARCHAR(20) ) PARTITION BY RANGE (sale_date) ( PARTITION p2023 VALUES LESS THAN ('2024-01-01') ); ``` --- ### **6. 安全与权限管理** - **权限控制** 支持标准 `GRANT`/`REVOKE` 语句,细化到列级权限(如 `GRANT SELECT (name) ON employees TO user1`)。 - **数据脱敏** 内置动态数据脱敏(Dynamic Data Masking),通过策略定义敏感字段的访问规则。 - **审计功能** 提供 `AUDIT` 语句记录 SQL 操作日志,满足合规要求。 --- ### **7. 高可用与灾备** - **容灾语句** 支持 `CREATE STANDBY DATABASE` 构建主备集群,通过 `SWITCHOVER` 实现故障切换。 - **在线 DDL** 允许 `ALTER TABLE` 操作(如添加索引)不阻塞业务读写。 --- ### **8. 兼容性与生态工具** - **Oracle/MySQL 兼容模式** 通过配置参数(如 `compatibility_mode = 'ORACLE'`)启用语法兼容,减少代码改造。 - **开发工具支持** 适配 JDBC、ODBC、Python 等主流驱动,提供与 Data Studio、DBeaver 等工具的集成。 --- ### **典型应用场景** - **金融核心系统**:依赖 ACID 事务与高并发能力。 - **政务 ERP**:利用分区表与存储过程处理海量事务。 - **电信计费**:通过分布式事务保障跨节点数据一致性。 --- ### **与 Oracle 的差异点** | 特性 | Gauss100 OLTP | Oracle | |--------------------|--------------------------------|--------------------------------| | **分布式架构** | 原生支持分片与全局事务 | 需依赖 RAC 或 Sharding | | **存储过程语法** | 兼容 PL/SQL(需配置模式) | 原生 PL/SQL | | **成本** | 开源版本免费,企业版按需订阅 | 商业授权费用较高 | --- 如果需要更具体的语法示例(如 JSON 处理、锁机制),可以进一步探讨!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值