# 影响性能的因素

## 磁盘划分

如果 OBSERVER 运行日志、事务日志、数据文件都在一块盘上，称为单盘部署。这个风险比较大，目前有一些已知问题。

+ 事务日志（CLOG) 空间利用率超过 80% 才开始回收，超过 95% 就节点停写、掉线。
+ 转储和合并时需要额外的 IO、CPU 资源，跟业务读写的 IO 可能会互相影响。
+ 运行日志（LOG）写的太多太快，可能导致节点掉线；LOG 写满可能导致节点异常。
+ 影响 `liboblog` 同步，影响 CLOG 回收或者副本迁移慢等。
+ 参数文件 `observer.config.bin` 因为盘满导致持久化失败。

以上影响 TPC-C 、SYSBENCH 测试多一些，对 TPC-H 影响少一些。

应对策略：

+ CLOG 、LOG、SSTABLE 分多个独立文件系统。不管是多盘还是单盘用 LVM 划分出多个 LV 。
+ 开启 LOG 限流，参数 `syslog_io_bandwidth_limit` 。 SQL： `alter system set syslog_io_bandwidth_limit='10M';`
+ LOG 滚动输出，设置最大数目。SQL： `alter system set enable_syslog_recycle=true; alter system set max_syslog_file_count=50;` 。
+ CLOG 参数 `clog_disk_usage_limit_percentage` 参数默认 95 ，不要轻易调大。`clog_disk_utilization_threshold` 默认 80，可以下调到 50，但是不能太低。

## OceanBase & OBPROXY 参数

### OceanBase 参数

```sql
alter system set net_thread_count = 32; -- 网络线程数 
alter system set _clog_aggregation_buffer_amount=4;
alter system set _flush_clog_aggregation_buffer_timeout='1ms' ; -- 把大概几毫秒之内的日志都聚合到一个rpc中发送，减小网络开销，提高并发读
alter system set trace_log_slow_query_watermark='10s' ;   --打印SQL QUERY的阈值
alter system set large_query_threshold='1s' ; -- large query的阈值，超过后进入大查询队列,避免大查询阻塞小查询
alter system set syslog_level='PERF'; -- 控制日志输出级别
alter system set clog_sync_time_warn_threshold='2000ms' ;  -- clog日志同步慢的时候触发debug日志的输出。
alter system set syslog_io_bandwidth_limit='10M' ;  -- 超过10M会日志限流，减小写日志文件带来的IO消耗
alter system set enable_sql_audit=false；  -- 关闭sql audit
alter system set enable_perf_event=false;   -- 关闭监控项
alter system set clog_max_unconfirmed_log_count=5000;  -- 增大滑动窗口，解决clog滑动窗口满导致的性能问题
alter system set minor_warm_up_duration_time=0 ; -- 转储sstable预热时间，转储完成后到预热时间内，所有对应partition的流量会逐步从memtable过渡到sstable，设置0转储之后流量马上切到sstable，使得memtable快速释放 ，内存释放更快。
alter system set clog_transport_compress_all = True;  -- 开启clog传输压缩，提高clog做Paxos同步的效率。但是会在clog传输前和接受后增加压缩的开销
alter system set enable_clog_persistence_compress = true;  -- 开启clog存储压缩，提高clog落盘效率。这个参数会减少clog落盘的IO，但是会在clog落盘前增加压缩的开销
alter system set memory_chunk_cache_size = '150G';  -- 降低OB内部2MB内存块被OS回收的概率，增大2MB内存块在OB内部的复用率，减少RPC由于内存操作慢而导致超时的风险。
alter system set minor_merge_concurrency = 32;  -- 增大转储的线程数，期望提高转储的速度。
alter system set _mini_merge_concurrency = 8;  -- 增大mini_merge的线程数，期望提高mini_merge的速度
alter system set freeze_trigger_percentage = 40;  -- 触发转储的时机
alter system set autoinc_cache_refresh_interval='86400s';  -- 调大自增列刷新的频率，减少性能损耗。
alter system set cpu_quota_concurrency=2;  -- 这个数*租户cpu=工作线程数，具体调整的数值需要根据业务模型和机器配置调整，工作线程超过实际CPU核数也没有意义同时会增加CPU调度和上下文切换的开销
alter system set builtin_db_data_verify_cycle = 0 ; -- 宏块巡检周期参数，当设置为0时关闭巡检 
alter system set micro_block_merge_verify_level = 0;  -- 微块校验等级设置，0：不做任何校验；1：对encoding做decode校验；2：对encoding做decode校验，对压缩做解压校验
alter system set _ob_get_gts_ahead_interval = '0ms'; 
alter system set bf_cache_priority = 10;  -- 为频繁空查的宏块建立bloomfilter并缓存，减少磁盘IO和CPU消耗，提升写入性能
alter system set user_block_cache_priority=5; 
alter system set merge_stat_sampling_ratio = 1 ;  -- 合并时统计信息采样率，当设置为0时则关闭统计信息采集
alter system set _enable_static_typing_engine=true; 

alter system set autoinc_cache_refresh_interval='86400s'; -- 调大自增列刷新的频率，对自增列和sequence场景有性能帮助
alter system set enable_early_lock_release=false tenant=all; -- 提前解行锁场景下，用于租户级别控制，是否打开该优化
```

### OBPROXY 参数

```sql
alter proxyconfig set enable_ob_protocol_v2=false ;
alter proxyconfig set enable_qos=false ;
alter proxyconfig set enable_compression_protocol=false ;
alter proxyconfig set automatic_match_work_thread = false;  -- 关闭自动计算线程个数
alter proxyconfig set work_thread_num = 32;  -- 手动设置工作线程个数，需要restart
alter proxyconfig set syslog_level='ERROR';
alter proxyconfig set monitor_log_level = 'ERROR';
alter proxyconfig set enable_monitor_stat = false ;
alter proxyconfig set xflush_log_level="ERROR";
```

### JDBC URL 参数

```bash
conn=jdbc:mysql://x.x.x.x(ip):xx(port)/xxxx(dbname)?rewriteBatchedStatements=true&allowMultiQueries=true&useLocalSessionState=true&useUnicode=true&characterEncoding=utf-8&socketTimeout=3000000
```

+ rewriteBatchedStatements ：该参数非常重要，会严重影响导数据效率，不可以忽略。
+ useLocalSessionState ：是否使用autocommit，read_only和transaction isolation的内部值(jdbc端的本地值)，建议设置为true，如果设置为false，则需要发语句到远端请求，增加发送请求频次，影响性能。

## 转储&合并

转储是租户级别的，当一台服务器中一个租户中MemTable的内存占用超过租户内存上限的一定比例时，就会触发小版本冻结（Minor Freeze）。所谓冻结，就是禁止当前活跃MemTable的写入，并同时创建新的空MemTable以支持新的写入。被冻结后的MemTable就成为一个静态的数据结构，可以被后台线程读取并转储为SSTable。

合并是全局级别的，合并会把当前大版本的SSTable和MemTable与前一个大版本的全量静态数据进行合并，产生新的全量数据。合并操作包含转储操作。

转储和合并是把内存数据刷到磁盘上，存储层统计信息可以更准确，生成的执行计划也就更稳定准确。
MemTable 扫描性能很差，合并后 RANGE 查询性能会有提升。

## PRIMARY_ZONE 设置

租户的 PRIMARY_ZONE 是用来控制租户里主副本的分布。如果设置为 RANDOM，就可以将不同分区的主副本分散在不同 ZONE 的节点上，机器利用率最大化。反过来，设置为某个具体的 ZONE，则只能利用部分节点。

## 使用分区表

分区表是使用一定的水平拆分策略将一个大表切割为多个独立的分区。独立的分区并不是分表，依然是分区表的一部分。

分区表有两个作用：

+ 将海量数据分散到不同分区存储，不同分区可以分散在不同节点存储，从而化解单机空间瓶颈。
+ 将海量请求分散到不同分区，不同分区主副本可以分散在不同节点，从而化解单机处理能力瓶颈。

分区表的索引分为全局索引和本地索引。
全局索引对某些不带分区键的查询比较友好，但是对写不友好，可能导致分布式事务。此外，当 RANGE 查询要返回很多数据时，全局索引也会有很多分布式查询，性能并不一定比本地索引好。
使用本地索引读写数据，可以规避分布式事务，可以多分区多节点并行读，性能也很不错。

## 使用表分组 TABLE GROUP

表分组是将一组业务联系紧密的表的分区分布调度在一起。

+ `table_group` ：TABLE GROUP 是一个逻辑概念，它和物理数据文件没有关联关系，TABLE GROUP 只影响表分区的调度方法，OceanBase 数据库会优先把属于同一个 Table Group 的相同分区号的分区，调度到同一台节点上，以减少跨节点分布式事务。
+ `partition_group`： TABLE GROUP 的每个分区表中下标相同的一组分区为 PARTITION GROUP，作用是将分区号相同的partition放到 1 个 PG 的物理结构里面达到提升性能的目的。

同一个表分组里面的分区表的分区策略必须一致。
