ob内存知识点

3.x 带事务转储
提交版本号肯定大于本地最大的读版本号
mvcc 如果 没有回填commit版本 不能判断版本号 读取上一个版本
回填了版本号 还没有全部提交 可能会被读到 则等待

1 读的是版本一致
2 要么全读 要么全不读

MEMSTORE:写入限流

2.x 不带事务转储
3.x
租户级别的参数
writing_throttling_trigger_percentage
writing_throttling_maximum_duration
超过了 writing_throttling_trigger_percentage 的memstore writing_throttling_maximum_duration 时间内 新申请的memstore业务将被限流
转储结束后 自动解除写入限制

写入限制为了给转储提供时间
转储 合并更新snapshot版本号

大事务 转储分层 内存使用相对平滑
转储(租户级别自动) ->整块整块的转储 内存连续
手动(分区) -->动态的分区级别转储(未来)–碎片很多

索引数量比较多也会造成内存使用放大
dml 之前查看分区大小 之后再看分区所占内存大小 -->得到内存放大倍速

buffer表自适应转储 独立于 租户的自动转储

buf Minor SSTable 来自于 (Mini + Major) 删除了空洞

memtable 转储后 no active
mvcc 超过十几个版本后 自动压缩 undo retention 之内的保留

#在 sys 租户下删除指定的计划缓存。
ALTER SYSTEM FLUSH PLAN CACHE GLOBAL tenant= ‘ob_test’;
ALTER SYSTEM FLUSH PLAN CACHE sql_id=‘B601070DFC14CB85FDA3766A69A9E1B3’
databases=‘myob1’ tenant= ‘ob_test’ GLOBAL; #普通租户登录 DBA 清除自己的计划缓存。
ALTER SYSTEM FLUSH PLAN CACHE sql_id=‘B601070DFC14CB85FDA3766A69A9E1B3’
databases=‘myob1’ GLOBAL;

GLOBAL 所有observer 全部适用

应用侧的优化思路
核心目的是减少应用与数据库的交互,减少花在“路上”的时间
1 高效的应用编码方法,把与数据库的多次交互“组合”在一起变为一次执行
2 合理的连接参数配置,减少无谓的数据库session变量、状态查询
3 应用缓存机制,把对数据库的访问变为对应用缓存的查询
保持交易与数据库连接的畅通,避免连接异常中断导致的交易报错
l 正确的应用连接池配置,科学的连接池管理

autocommit /read_only/隔离级别

rpc调优
observer之间网络延迟压到最低 调整rpc/io参数 服务器
调整软中断参数 打散 分散到多个cpu上 每个cpu上的软中断不要超过20%
网卡调优缩短链路
去两道防火墙 防护墙的替代(白名单)
从1.2s 降低到 200ms
4条10GB机房间网络 10公里

[RPC EASY STAT](log_str=“conn count=10/10, request done=xxxxxx/xxxxxx, request doing=xxxxxx/xxxxxx”)
? request done= in_requests_done/out_requests_done 收到了多少请求
? request doing=in_requests_doing/out_requests_doing 正在做的请求
如果RPO IO线程的request doing 的in和out不都为0,说明该线程处于工作状态。如果系统所有RPO
IO线程都处于工作状态,则说明RPC线程比较繁忙
此时需要增加rpc线程数

obclirnt sys 租户
alter proxyficong set enable_compression_protocol=false; – 不使用压缩协议进行传输,重启生效
alter proxyconfig set automatic_match_work_thread = false; – 关闭自动计算线程个数,重启生效
alter proxyconfig set work_thread_num = 32; – 手动设置工作线程个数为32个,重启生效
alter proxyconfig set proxy_mem_limited = ’12G’; – 设置proxy的内存上限为12G

OBProxy 事务路由
推荐设置ob_proxy_readonly_transaction_routing_policy=False,让OBProxy对DML语句的路由以第一条实际开
启事务的语句为准,对事务开启前只读语句可以正确路由,减少远程执行的SQL数量

4.x 每一条sql自由路由

TCP !"#$%server&
alter proxyconfig set sock_option_flag_out = 3; – '( TCP NO_DELAY ) KEEPALIVE
alter proxyconfig set server_tcp_keepidle = 5; – '*KEEPALIVE+,-.idle/0152
alter proxyconfig set server_tcp_keepintvl = 5; – 34KEEPALIVE+,5.67/008152
alter proxyconfig set server_tcp_keepcnt = 2; – 9:67.KEEPALIVE +,54$124
alter proxyconfig set server_tcp_user_timeout = 0; – ;<TCP=ACK>?@A.B//C10 DEFGB/HI
TCP !"#$%client&
alter proxyconfig set client_sock_option_flag_out = 2; – ‘(KEEPALIVE1F’(TCP NO_DELAY
alter proxyconfig set client_tcp_keepidle = 5; – '*KEEPALIVE+,-.idle/0152
alter proxyconfig set client_tcp_keepintvl = 5; – 34KEEPALIVE+,5.67/008152
alter proxyconfig set client_tcp_keepcnt = 2; – 9:67.KEEPALIVE +,54$124
alter proxyconfig set client_tcp_user_timeout = 0; – ;<TCP=ACK>?@A.B//C10 DEFGB/HI

分区键必须是主键或唯一键的子集
先做本地唯一的判断 才做全局唯一的判断

一致性hash算法 分区数变化时 每个分区拿出一小部分数据重新分区

全局索引跟表独立 更新索引=分布式事务
分区表上创建索引时,默认为全局索引,建立本地索引需要指定LOCAL关键字
对分区表来说,其上创建的全局索引可以视为一个有关联的独立的索引表
l 分区表与全局索引分布在不同的OBServer上,使用全局索引可能会产生分布式事物
2 建议尽可能的使用本地索引,只有在有必要(唯一性、性能)的时候才使用全局索引
如何选择全局和局部索引 (举例:局部索引造成性能降低, 改用全局索引后提高性能,对比执行计划)

非分区表只有本地索引

insert 隐式的开启事务 决定 scheduler

负载均衡
表组级别的均衡 ->考虑表的负载均衡(分区负载均衡):每一个observer上副本数/leader数相同

在OceanBase数据库中,基于规则的路径选择主要用于索引选择
l 前置规则:强匹配的规则体系,直接决定一个查询使用什么样的索引
? 匹配"唯一性索引全匹配+不需要回表(主键被当成唯一性索引来处理)“时,选择该索引。如果存在多个这
样的索引,选择索引列数最小的一个
? 匹配"普通索引全匹配+不需要回表"时,选择该索引。如果存在多个这样的索引,选择索引列数最小的一个
? 匹配"唯一性索引全匹配+回表+回表数量少于一定的阈值”,则选择该索引。如果存在多个此匹配类型的索引,
选择回表数量最小的一个
l 剪枝规则:在特定的维度上比较两个索引,如果一个索引优于另外一个索引,那么不优的索引会被剪掉,最后没
有被剪掉的索引会进行代价比较,从而选出最优的计划。剪枝规则定义三个维度: ? 是否回表:索引包含所有需要访问的列,则不需要回表
? 是否存在 Interesting Order:利用索引的有序性来避免排序
? 索引能否提供 Query Range的匹配:在存储层可以直接确定查询范围

普通索引的回表逻辑封装在 TABLE SCAN 算子中;全局索引的回表逻辑由 TABLE LOOKUP 算子完成(先找到分区)

当租户配置项 enable_sql_extension 为 TRUE 的时候,可以使用 Oracle 模式的语法

ALTER SYSTEM SET ENABLE_SQL_EXTENSION = TRUE;
ANALYZE TABLE tbl1 COMPUTE STATISTICS FOR ALL COLUMNS SIZE 128;

索引的第一列会做统计信息收集
没有索引 必须收集直方图

analyze table test update histogram on b with 20 buckets;
select table_id, column_id, distinct_cnt,null_cnt,max_value,min_value,sample_size, bucket_cnt, histogram_type from
oceanbase.__all_column_stat_v2 where table_id=50001 and column_id=17;
±---------±----------±-------------±---------±----------±----------±------------±-----------±---------------+
| table_id | column_id | distinct_cnt | null_cnt | max_value | min_value | sample_size | bucket_cnt | histogram_type | ±---------±----------±-------------±---------±----------±----------±------------±-----------±---------------+
| 50001 | 17 | 8 | 0 | 8 | 1 | 2550 | 8 | 1 |
±---------±----------±-------------±---------±----------±----------±------------±-----------±---------------+
select table_id,partition_id,column_id,endpoint_num,endpoint_value,endpoint_repeat_cnt
from __all_histogram_stat_v2 where table_id=50001 and column_id=17;
±---------±-------------±----------±-------------±---------------±--------------------+
| table_id | partition_id | column_id | endpoint_num | endpoint_value | endpoint_repeat_cnt | ±---------±-------------±----------±-------------±---------------±--------------------+
| 50001 | 0 | 17 | 10 | 1 | 10 |
| 50001 | 0 | 17 | 30 | 2 | 20 |
| 50001 | 0 | 17 | 70 | 3 | 40 |
| 50001 | 0 | 17 | 150 | 4 | 80 |
| 50001 | 0 | 17 | 310 | 5 | 160 |
| 50001 | 0 | 17 | 630 | 6 | 320 |
| 50001 | 0 | 17 | 1270 | 7 | 640 |
| 50001 | 0 | 17 | 2550 | 8 | 1280 |
±---------±-------------±----------±-------------±---------------±--------------------+

存储搜集的统计信息
OceanBase存储层会动态搜集一些搜集信息
表的记录数
索引首列的统计信息
1列中不同的值的数量(NDV)
2 列中NULL值的数量
3 列的最大值和最小值

存储层搜集是后台自动实时运行 不落盘 优先级更高
存储层搜集的统计信息不会更新到相关的统计信息表 不会落盘
存储层搜集的统计信息是基于本地的统计,对于非分区表的统计相对准确,对于分区表的统计差异较大
对于日内数据量不稳定的表,比如日清的日志表,存储层的统计信息搜集帮助优化器进行更准确的选择率估算和路径选择

查看统计信息

select OWNER,TABLE_NAME,NUM_ROWS,LAST_ANALYZED from ALL_TAB_STATISTICS where table_name=‘TEST’;
±------±-----------±---------±--------------+
| OWNER | TABLE_NAME | NUM_ROWS | LAST_ANALYZED |
±------±-----------±---------±--------------+
| GTX | TEST | NULL | NULL |
±------±-----------±---------±--------------+
select OWNER,TABLE_NAME,COLUMN_NAME,NUM_DISTINCT,LOW_VALUE,HIGH_VALUE,NUM_NULLS,LAST_ANALYZED from
ALL_TAB_COL_STATISTICS where table_name=‘TEST’;
±------±-----------±------------±-------------±----------±-----------±----------±--------------+
| OWNER | TABLE_NAME | COLUMN_NAME | NUM_DISTINCT | LOW_VALUE | HIGH_VALUE | NUM_NULLS | LAST_ANALYZED |
±------±-----------±------------±-------------±----------±-----------±----------±--------------+
| GTX | TEST | C1 | NULL | NULL | NULL | NULL | NULL |
| GTX | TEST | C2 | NULL | NULL | NULL | NULL | NULL |
| GTX | TEST | C3 | NULL | NULL | NULL | NULL | NULL |
±------±-----------±------------±-------------±----------±-----------±----------±--------------+
select * from ALL_TAB_HISTOGRAMS where table_name=‘TEST’;

当估算选择率依赖的统计信息缺失时,或者谓词条件、连接条件过于复杂、无法精确估算选择率,优化器会使用默认
的统计信息和选择率
n 默认的统计信息
l 表记录数:100000
l 列NDV数:100
n 默认的选择率:
谓词 示例 选择率
col = ? T1.C1 = 100 1/100
col is null T1.C1 is NULL 1/100
col <> ? T1.C1 <> 100 99%
col op ? T1.C1 > 100 10%
col BETWEEN ? AND ? T1.C1 BETWEEN 100 AND 200 5%
fuction(col) = ? SUBSTR(C3,2,1)=‘b’ 0.5%

  • 注释: op 为范围比较符号 > , <, >= , <=

DFO 本任务内串行执行

OceanBase数据库目前主要支持以下数据分发的方法:
l Partition-Wise Join 分区表且分区方式相同,物理分布一样 tablegroup
2 Partial Partition-Wise Join(又称做PARTITION分发或PKEY Join) 发送分区数据到另一个分区 当内外表中一个表为分区表,另一个表为非分区表,或者两者皆为
分区表但是连接键仅和其中一个分区表的分区键相同的情况下,会以该分区表的分区分布为基准,重新分布另一个表的数据
3 Hash-Hash重分布 join条件不在分区键和索引 使用连接键上的哈希函数,将每个表的行映射到查询服务器。映射完成后,每个查询服务器都会在一对结果分区之间
执行连接
t1、t2按照连接键t1.v2、t2.v2做hash,把数据分成8份,分发给相应的8个worker线程
4 Broadcast重分布 小表所有的数据给另一个表每个分区发送一份完整的数据 存储层判断小表
5 Random重分布 Random重分布主要适用于UNION ALL的场景,将小表的数据随机(round robin)地发送到另一张表的分区所在的
服务器

并行查询要用 traceid
SELECT svr_ip,plan_id,plan_type, qc_id,dfo_id,sqc_id,worker_id,is_executor_rpc, elapsed_time
FROM oceanbase.gv$sql_audit WHERE trace_id = 'YB420BA6566F-0005E3D3694EAC9F-0-0’
order by qc_id,sqc_id

qc_id: scheduler
is_executor_rpc: 任务分发者

1 个赞