分区表概述
分区表的概念:OceanBase 数据库可以把普通的表数据按照一定的规则划分到不同的区块内,同一区块的数据物理上存储在一起。这种划
分区块的表叫做分区表,其中的每一个区块称作分区
分区表的适用场景
并行处理
热点打散
数据管理
OceanBase 数据库中分区表的特点
OceanBase 数据库自动对表、分区在多个节点间进行负载均衡和多副本容灾。
OceanBase 可动态多机扩展,并在分区间并行查询。
分区的分布对业务透明,可以取代MySQL 的“分库分表”方案。
单表的最大分区数:
MySQL 模式由租户配置项max_partition_num 控制,默认值8192。
Oracle 模式是65536。
单机分区数支持上限:根据租户内存大小来预估,每1GB 内存约支持20000 分区
分区策略
OceanBase 支持的分区策略包括范围(Range)分区、列表(List)分区和哈希(Hash)分区
OceanBase 支持组合分区,即先使用一种分区策略,然后在子分区再使用另外一种分区策略
MySQL 范围分区 range /range columns 列表分区 list /list columns 哈希分区 hash /key
ORACLE 范围分区 range 列表分区 list 哈希分区 hash
不同分区策略下的分区键选择规则:
分区键必须是主键或唯一键的子集。只要表有主键,分区键就必须是主键的子集。
MySQL 模式下,RANGE、LIST、HASH 的分区键必须是单个列或表达式,且必须是整数类型或YEAR 类型;RANGE COLUMNS、LIST COLUMNS、KEY 的分区键可以是多个列,但不支持表达式,并支持除BLOB、TEXT 外的大部分数据类型。
Oracle 模式下,RANGE、LIST、HASH 的分区键规则与MySQL 模式下RANGE COLUMNS、LIST COLUMNS、KEY 相似
组合分区
组合分区按照两个维度来对数据分区:先按一种分区策略拆分一级分区,然后再按另一种分区策略将每一个一级分区拆分成二级分
范围分区、列表分区和哈希分区都可以作为组合分区表的一级分区与二级分区策略。
组合分区的示例:
CREATE TABLE history_t (user_id INT,
gmt_create DATETIME, info VARCHAR(20),
PRIMARY KEY(user_id, gmt_create))
PARTITION BY RANGE COLUMNS (gmt_create)
SUBPARTITION BY HASH(user_id) SUBPARTITIONS 3
(PARTITION p0 VALUES LESS THAN (‘2024-11-11’),
PARTITION p1 VALUES LESS THAN (‘2025-11-11’),
PARTITION p2 VALUES LESS THAN (‘2026-11-11’),
PARTITION p3 VALUES LESS THAN (‘2027-11-11’) );
上面的表一共有几个分区
3*4=12 ,一共12个分区
分区管理-添加分区
Oracle模式中:
对于一级分区表,当前仅支持对Range 分区和List 分区执行添加分区操作,暂不支持对Hash 分区执行添加分区操作。
对于二级分区表,当前仅支持对Range/List 类型(组合)的分区执行添加分区操作。
仅支持向非模板化二级分区表中添加二级分区。
MySQL模式中:
暂不支持向表中添加二级分区。
对于一级分区表,支持Range / Range Columns / List / List Columns执行添加分区操作,暂不支持对Hash分区和Key分区执行添加分区操作。
分区管理-删除分区
根据业务需要,删除分区表中的分区。删除分区时,会同时删除该分区的定义和数据
删除分区时,尽量保证待删除的分区上不存在活动的事务或查询,否则可能会导致SQL 语句报错,或者出现一些异常情况。可在sys 租户通过视图oceanbase.GV$OB_TRANSACTION_PARTICIPANTS 查询当前还未结束的事务上下文状态
Oracle模式中:
对于一级分区表,当前仅支持对Range 分区和List 分区执行删除分区操作,暂不支持对Hash 分区执行删除分区操作。对于二级分区表,当前仅支持对Range/List 类型(组合)的分区执行删除分区操作。
对于有全局索引的一级分区表或二级分区表,删除分区时,需要添加UPDATE GLOBAL INDEXES来更新全局索引信息。如果未添加,删除分区后该分区表上的全局索引会处于不可用状态
MySQL模式中:
对于一级分区表,支持Range / Range Columns / List / List Columns执行删除分区操作,暂不支持对Hash分区和Key分区执行删除分区操作
分区表索引概述
局部分区索引
全局索引
唯一索引
前缀索引
非前缀索引
表组概述
表组的概念:表组(Table Group)是一个逻辑概念,表示一组表的集合。OceanBase 依据表组的SHARDING 属性控制组内表和分区的物理分布,使表组内的表或不同表的相同分区聚合在相同的服务节点上。
表组的适用场景:通过表组将业务相关联的表按照一定的规则进行物理上的聚合,避免跨节点的数据访问,避免分布式事务,提升查询和交易的性能。
表组4X可设置3个属性 NONE、PARTITION、ADAPTIVE
NONE属性对表的分区规则没有要求表组内的表可以是分区表也可以是非分区表,表组内的所有的表都会聚集到一个节点,优点非常灵活,缺点分区表的所有分区都需要聚集到一个节点,不能做到热点数据的打撒
PARTITION 所有表的一级分区需要相同,包括分区的个数也必须相同,
第一张表的一级分区平均分布到所有的节点上;
其他表的相同分区号的一级分区与第一张表聚集;
若表有二级分区,则一级分区下的所有二级分区聚集在一起。
优点要求所有的表二级分区可以不同,使用起来相对灵活,如果表存在二级分区,那么相同一级分区下的二级分区会聚集到一起,不能做到二级分区数据的热点数据打散
ADAPTIVE 所有表的分区规则完全相同,要么都不分区,要么都是相同的一级分区,或者都是相同的组合分区。
如果仅有一级分区,则与SHARDING=PARTITION 相同;
如果都是组合分区,则按二级分区打散,相同的二级分区聚集在相同的节点上。
将表加入表组的方法有三种:
- 创建表时,直接指定其所属的表组:CREATE TABLE … TABLEGROUP = tablegroup_name;
- 创建表后,修改表来指定表组:ALTER TABLE … TABLEGROUP = tablegroup_name;
- 创建表后,修改表组来添加表: ALTER TABLEGROUP tablegroup_name ADD table_name [, table_name…];
将表从表组中移除:
ALTER TABLE table_name DROP TABLEGROUP;
ALTER TABLE table_name [SET] TABLEGROUP=’’;
删除表组的语法:
DROP TABLEGROUP tablegroup_name ;
注释:仅当表组为空时,即没有任何表指定TABLEGROUP 属性为该表组时,才可以删除该表组。
表组查询
系统租户和MySQL 用户租户可以分别通过视图CDB_OB_TABLEGROUPS 和视图DBA_OB_TABLEGROUPS 来查看表组的SHARDING属性及表组内表的分区信息。
Oracle 用户租户可以通过视图DBA_OB_TABLEGROUPS 来查看表组的SHARDING 属性及表组内表的分区信息
可以通过SHOW TABLEGROUPS 语句查看表组内表的所属数据库及表组的SHARDING 属性。
创建表组后,根据业务调整,可以使用ALTER TABLEGROUP 语句修改表组的SHARDING 属性。
ALTER TABLEGROUP tablegroup_name SHARDING = ‘NONE’|‘PARTITION’|‘ADAPTIVE’ ;
修改规则:
将表组的SHARDING 属性修改为NONE 时,可直接修改
将表组的SHARDING 属性修改为PARTITION 时:
如果表组内的表都是非分区表,可以直接修改。
如果表组内同时有非分区表和分区表,无法修改。
如果表组内的表都是一级分区表或者组合分区表,要求所有表的一级分区对应的分区规则完全相同,否则无法修改。
将表组的SHARDING 属性修改为ADAPTIVE 时:
如果表组内的所有表都是非分区表,可以直接修改。
如果表组内同时有非分区表和分区表,无法修改。
如果表组内同时有一级分区表和组合分区表,无法修改。
如果表组内全部是一级分区表或者全部是组合分区表,要求所有表的分区规则完全均相同,否则无法修改。
注意:OceanBase 数据库升级过程中,禁止使用ALTER TABLEGROUP 语句修改表组的SHARDING 属性。
复制表概述
复制表的概念:复制表是OceanBase 数据库中一种特殊类型的表。复制表会在租户的每一个服务节点上创建一份数据副本,OceanBase 可以在任意一个“健康”的副本上读取到数据的最新修改,而普通表只有主副本才能保证读到最新的数据
复制表的适用场景:
复制表适用于读多写少且数据量较小的表,比如参数表。
复制表用于解决跨机读取数据的性能问题,通过在每个服务节点上复制一份数据,让读请求都可以在本地完成。
OceanBase V4.2 版本中复制表的特点:
复制表会在租户的每一个UNIT 内各创建一个副本,以满足大量并发的读请求。
复制表只有一个Leader 副本,可以接受写请求;复制表的所有“健康”副本都能接受强一致性读请求。
OceanBase 基于分区的可读版本号校验以及基于日志流的Lease 授予机制,用于保证强一致性读的正确性。
租户在Zone 内有多个UNIT 时,其中一个UNIT 按照Locality 描述分配该zone 的副本类型,其他Unit 上均分配只读型副本(Listener)。
广播日志流
OceanBase V4.2.0 版本开始引入了广播日志流的概念,广播日志流是一个特殊的日志流,用于租户内所有复制表的副本同步。广播日志流会在租户内的每个OBServer 节点上均部署一个副本,保证在理想情况下复制表可以在任意一个OBServer 节点上提供强一致性读。
一个租户只有一个广播日志流,承载租户内所有的复制表
广播日志流在所有非只读副本间强同步。
如何使用复制表
CREATE TABLE table_name … DUPLICATE_SCOPE=‘none | cluster’;
NONE代表普通表,cluster代表复制表,
一个3-3-3的集群中,所有表的DUPLICATE_SCOPE=‘NONE’,问这个集群中每个分区最多有几个副本,答案是3个副本,如果存在表的DUPLICATE_SCOPE=‘cluster’ 那么每个分区最多可能存在9个副本
系统视图DBA_OB_TABLE_LOCATIONS 的DUPLICATE_SCOPE 字段标识了表的复制表属性:
复制表创建成功后,可以与普通表一样进行插入和读写操作。不同的是,对于读请求,如果使用Proxy 的方式连接数据库,则读请求可能会路由到任意一个OBServer 节点执行;如果是通过直连方式连接数据库,则只要本地副本可读,系统就会在直连的OBServer节点上执行读请求
Buffer 表概述
Buffer 表的概念:Buffer 表又被称为Queuing 表,意为业务上“像使用buffer 一样使用一张表”。通常情况下,Buffer 表实际的数据量不大,但在业务执行过程中会有大量的更新操作或者插入再增删操作。
指定Buffer 表的合并策略 极低、低、中、高、极高
NORMAL、QUEUING、MODERATE、SUPER、EXTREME
1.修改表的语句执行成功后,系统会有一定的延时(大约2 分钟),待修改生效后,系统将以配置的合并模式调度自适应合并以解决Buffer 表现象。
2.在V4.2 版本中,表的table_mode 属性只能通过SHOW CREATE TABLE 的方式查看,系统表暂不提供table_mode 的查询。
序列和自增列概述
序列(SEQUENCE)是一个独立的数据对象,用于提供全局唯一的数值。
默认设置下,序列仅保证单节点内单调有序,不保证全局有序。
序列提供两个伪列:CURRVAL 是序列的当前值,NEXTVAL 是序列的下一个值。
每个序列可以单独定义其CACHE、ORDER 等属性。
MySQL 模式和Oracle 模式均支持序列,且实现机制相同。
自增列(AUTO INCREMENT)是隶属于表的列,具备单调有序且唯一的属性。
默认设置下,自增列保持全局有序。
插入数据时不指定自增列的值,由数据库来自动生成单条有序的数值。
每个表可以单独定义其自增列的ORDER 属性,自增列的CACHE 等属性则通过租户变量参数来控制。仅MySQL 模式支持自增列。
OceanBase 数据库V4 版本中,自增列与序列的实现机制不同。自增列可以使用集中缓存来提供全局有序的递增值,而序列在使用缓存时
无法提供全局有序的值。
查看序列的定义:
在MySQL 模式下,可以通过DBA_SEQUENCES 或DBA_OB_SEQUENCE_OBJECTS 视图查看创建的序列;
在Oracle 模式下,可以通过DBA_SEQUENCES、USER_SEQUENCES、ALL_SEQUENCES 视图查看创建的序列。
使用ALTER SEQUENCE 语句修改序列的属性,使用DROP SEQUENCE 语句删除序列。
- 查看序列的CURRVAL 之前,当前SESSION 须先访问过该序列对象的NEXTVAL,否则会报“sequence is not yet defined in this session” 错误。
- 每次查询NEXTVAL 都会推进CURRVAL 值。
序列模式的选择建议:
OceanBase 数据库中,序列使用ORDER with NO CACHE 模式时,每次调用NEXTVAL 都会触发一次内部表SELECT 与UPDATE 操作,会影响数据库的性能。
出于性能考虑,我们不建议使用默认的CACHE with NOORDER 模式,不建议使用ORDER with NO CACHE 模式。
CACHE 大小的设置建议:
在创建序列时,由于默认的CACHE 值只有20,按照序列的使用频率,合理分配CACHE 的大小。建议每日CACHE刷新的次数控制在100 次以内。例如,对于单机TPS 为100 时,CACHE SIZE 建议设置为360000。
序列值跳变的原因:
缓存在CACHE 中的序列值在发生服务器重启或者切主等操作时会失效,OceanBase 数据库在服务器重启或者切主后会重新分配、缓存序列值,导致序列值的跳变
OceanBase 数据库V4 版本的自增列支持两种自增模式:
ORDER 模式(默认):基于集中缓存的自增列。设置为该模式后,自增列的值全局递增且唯一。
NOORDER 模式:基于分布式缓存的自增列,设置为该模式后,仅保证自增列的值全局唯一。
自增列默认是 cache+order 的 auto_increment_mode是 order 缓存 1000000 采用集中式缓存
OceanBase 数据库优化器基于规则和代价模型,生成最优的执行计划。规则只适用于单表访问的索引选择,更多时候是基于代价的选择。
基表访问的代价通常取决于扫描的行数、回表的行数。
关联查询的代价通常取决于连接算法、连接的结果集大小。
执行计划调优是人为优化或干预优化器的执行计划选择,常见的调优手段有:
优化索引:创建最优索引,提供更好的性能。
搜集统计信息:提供全面、及时的统计信息,帮助优化器更准确地估算扫描和返回的数据量。
指定执行计划:使用Hint 或Outline 来指定执行计划。
执行计划演进:使用SPM 来管理和演进执行计划。
使用并行查询:通过并行处理来提高AP 类查询的性能。
改写SQL:比如提供更优的过滤条件,避免使用复杂谓词条件,或者将标量子查询改写为Join。
单表扫描
Table Scan 算子分为以下几类:
TABLE FULL SCAN(全表扫描):完整扫描整个表或分区,该扫描方式不会使用索引过滤。
TABLE RANGE SCAN(范围扫描):扫描特定范围的记录,该扫描方式通常使用索引或主键来过滤扫描范围。 --考试遇到过的原题
该扫描方式通过匹配索引或主键的前缀列,来确定扫描的范围(query range) 。
TABLE SKIP SCAN(跳跃扫描):跳跃地方式扫描不连续的几个范围,该扫描方式通常使用索引或主键来执行跳跃。
该扫描方式通过匹配索引或主键的后缀列,来确定跳跃扫描的范围(skip scan range) 。
TABLE GET(主键唯一匹配): 直接用主键唯一查询,匹配0 行或者1 行数据。
OceanBase 数据库在满足如下限制条件时会尝试选择TABLE SKIP SCAN:
表上有收集过统计信息。
查询条件中包含联合索引的后缀列,并且不是其他索引最左前缀。
前缀列包含的不同值的个数(NDV)较少。
优化器比较TABLE SKIP SCAN 和全表扫描的代价,发现TABLE SKIP SCAN 代价更低。
最佳的索引设计应该满足以下特征:
最好的过滤性能:索引列能匹配最好的过滤条件,尽量少地扫描索引表,并且索引扫描后返回尽量少的记录。
覆盖索引:索引列尽可能包含SQL 查询所需的所有过滤列和投影列,避免回表访问。
避免排序:索引列的顺序与Order By 或者Group By 的列顺序一致,避免对查询结果进行排序
在OceanBase 数据库中,索引是一个B+ 树结构,索引扫描遵循B+ 索引的匹配规则:
条件的先后顺序不影响索引能效,如where A = ? and B = ? 和where B = ? and A = ? 效果相同
按照索引字段的顺序匹配,一旦前面的索引字段缺失,后面的索引字段无法参与匹配
遇到第一个范围查询字段后,后续的字段不参与匹配
查询条件中的索引字段如果不能参与匹配,依然可以提供扫描过滤
使用HINT 指定执行路径
HINT 的位置必须紧跟在DELETE、INSERT、MERGE、SELECT 或UPDATE 关键字后面。–可能出考题,四个选项四个语句,每个语句一个HINT,问那些写法是正确的
与普通SQL 注释所不同的是,HINT 需要在注释的左标记后(’/*’ 符号)增加了一个’+’。
如果一次使用多个Hint,则Hint 间需要用空格或者逗号分隔。
HINT 只影响优化器生成计划的逻辑,而不影响SQL 语句的语义。
如果使用MySQL 的C 客户端执行带Hint 的SQL 语句,需要使用-c 选项登录,否则MySQL 客户端会将Hint 作为注释从用户SQL语句中去除,导致系统无法收到用户Hint。
可以使用Hint 指定表扫描的执行方式,比如使用哪个索引
INDEX(table_name index_name) 设置表索引,index_name 为PRIMARY 时表示主键
FULL(table_name) 设置表执行计划为主表(主键),等价于INDEX(TBL_NAME PRIMARY)。 – 考试遇到的题
INDEX_SS(table_name index_name) 设置表执行计划为TABLE SKIP SCAN。
CREATE OUTLINE 绑定执行计划
使用Hint 指定执行计划需要修改SQL 语句,通常需要应用开发人员修改程序。OceanBase 数据库同时提供了Outline 从数据库侧为SQL绑定执行计划Hint,而无需修改SQL 语句。
CREATE OUTLINE otl1 ON SELECT /+ INDEX(t1 idx_c2)/ * FROM t1 WHERE c2 = 1;
此outline生效的语句为 SELECT * FROM t1 WHERE c2 = 1;
使用SQL_ID 创建Outline 时,可以通过以下方法获取SQL 的SQL_ID:
通过查询SQL 监控的系统视图,比如GV$OB_PLAN_CACHE_PLAN_STAT、GV$OB_SQL_AUDIT 获取。
通过参数化的原始SQL,使用MD5 生成SQL_ID 。 此处需要注意获取SQL_ID需要先把原始的SQL进行参数话,然后才能获取到SQL_ID,不是获取SQL_ID之后在进行参数化,这个地方会出考题
确认OUTLINE 是否生效
创建Outline 后,可以通过系统视图DBA_OB_OUTLINES 或DBA_OB_FORMAT_OUTLINES 确认是否创建成功。
执行绑定的SQL,从Plan Cache 中判断SQL 是否通过绑定的Outline 生成了新执行计划。
如果outline_id 与在DBA_OB_OUTLINES 中查到的outline_id 相同,则表示是按绑定的Outline 生成的执行计划,否则不是。
执行计划管理(SPM)
管理SPM的程序员包为dbms_spm
统计信息概览
此处会出题需要注意
表的统计信息 数据量:行数 空间大小:宏块数、微块数 行的长度:平均行长
列的统计信息 NULL 值:NULL 值的记录数 NDV:不同的值的个数 范围:最大值、最小值 列的长度:平均列长 直方图:频率:特定值的记录数 范围:范围内的记录数 (频次直方图、TOP K直方图、混合直方图)
索引的统计信息 数据量:行数 空间大小:宏块数、微块数 行的长度:平均行长
统计信息收集
手动收集 自动收集 在线收集
手动收集统计信息:DBMS_STATS
除非指定了method_opt,搜集schema 或table 的统计信息时,默认不搜集列的直方图信息。
在线收集统计信息
在线统计信息收集指在批量插入或导入数据时,数据库优化器同时收集统计信息,不用手动调用系统包。
支持在线统计信息搜集的场景主要有:
CREATE TABLE AS SELECT:默认启动在线收集统计信息功能。
INSERT INTO … SELECT:满足以下任一条件时,开启在线收集统计信息功能。
使用PDML(Parallel DML)
使用旁路导入(Append)
指定Hint:GATHER_OPTIMIZER_STATISTICS
自动收集统计信息
过期判断:从上一次收集统计信息后,该表或分区的增/删/改的比例达到阈值,默认10%,则认为该表或分区的统计信息过期。
收集策略:统计信息收集的粒度、范围以及并发度等,还有统计信息的过期阈值,以及历史统计信息的保留时间等。
收集窗口:数据库优化器定义了周一到周日7 个自动统计信息收集任务,按照配置的时间窗口进行统计信息的自动收集。
自动统计信息收集中,判断一个表的统计信息是否过期,主要依据上一次统计信息收集时间到本次收集期间该表的做增/删/改的比例(默认10%),OceanBase 数据库优化器也提供了相关视图用于查询一张表的增/删/改次数。
字段说明
INSERTS/UPDATES/DELETES:统计自上一次自动收集统计信息以来的DML 执行次数,转储合并后显示的是DML 修改的记录个数。
TRUNCATED:指示上一次自动收集统计信息后该表、分区是否被Truncate 过。
DROP_SEGMENTS:自上次分析以来删除的分区和子分区段数。