ITPub博客

首页 > 数据库 > Oracle > X86比小型机要慢很多?--技术人生系列第四十八期-我和数据中心的故事

X86比小型机要慢很多?--技术人生系列第四十八期-我和数据中心的故事

Oracle 作者:记录每一次错误 时间:2018-12-04 10:58:07 0 删除 编辑

一、问题描述


某大型国有银行的一套业务系统,近期由小型机迁移至X86环境。据项目组反映部分DB_LINK查询比原来小型机慢。这不对啊,相同的存储,CPU也更多,内存也更大。

于是 DBA随手挑出一张大表,做个简单的COUNT(*)查询,发现Linux比AIX慢了6倍 。重复执行多次,结果也类似。难道委屈项目组了,这套 X86 就是比小机慢? 于是找上中亦,深入分析下问题原因。


执行时间对比


AIX 下执行时间为 3 分 10 秒


Linux 下 执行 时间为 19分 3 秒


相同 SQL 语句在, AIX 环境下执行时间为 Linux 下执行时间快 6 倍。


二、问题排查


环境有何差异

现场的环境配置如下表:

看得出, Linux配置确实比AIX 来的高 。


其他表试试?


既然每次 执行 TAB1 , Linux 都会比AIX慢6 ~7 倍,那不如我们换张表试试,这边我随机测试了5 张 表,结果 Linux 都会比 AIX 快20 % 。那么问题肯定和这张表有关。

 

是不是 Linux 环境上该表上碎片太多了?不对,我们先看执行计划和等待事件 。


执行计划


检查 2 个 环境的执行计划是否一致,都是走 Index   Fast Full Scan

等待事件应该为“ db file scattered read ”


AWR 对比分析


抓取当时的 AWR 报告进行对比 分析 :

AIX 环境:

多块读仅仅等待了 694 次,每次 11 毫秒。

Linux环境:

多块读等待了 98921 次,单次等待 9 毫秒 。


现场真实执行一次


在 AIX 和 Linux 环境, 同时对 TAB1 表执行 COUNT(*) 查询,观察ASH视图。

Linux 环境:

首先查询到此次执行的 SQL_EXEC_ID 。 11 g 引入该字段真的是太好用了,标记出每个连接在执行相同的 SQL 语句时候的执行序号

AS H 默认 抓取间隔是 1 秒 ,该次执行 花费 了至少 943 秒

考虑到 db file scattered read   等待事件可能受到参数 db_file_multiblock_read_count 的影响,当数据存储不够连续时候,可能增加多块读等待次数。


该等待事件 P3 代表 BLOCKS , 其含义可以从 P3TEXT 列看出,为此次等待请求读取的数据块数目。

该次执行中, P3 的平均值为 31.96 ,接近主机参数 db_file_multiblock_read_count=32 ,可以判断出数据存储,基本是连续的。


AIX 环境:

查询到此次执行的 SQL_EXEC_ID, 继续查看该次执行等待多块读的次数

在AIX环境下没有进行一次多块读, 让我们看看等待事件是什么?

不对, AIX和 Linux 环境好像都开启了 EVENT 10949 ,不应该出现直接路径读 。


三、寻找规律


多块读的执行方式


在Oracle 11.2版本,对表或者索引的大小存在2个界限。

进行 全表扫描 ( Table Full Scan) 或者索引 快速全 扫描( Index Fast Full Scan) 时候 , 会 将对象的大小 ,和 STT 和 VLOT 进行对比 。所以 当表 或者 索引的大小超过 某个 阈值, 即使 设置 了 EVENT 10949 , 仍然 会 出现直接路径读 。


为了验证 Oracle 数据库 如何选择多块读的执行方式,我们开启的 NSMTIO 跟踪,从 Trace 文件 中可以看到 VLOT 的计算值 。

生成 的 Trace文件 示例如下 , 包含了 Object Size和 VLOT ,其单位都是 BLOCK 。


验证 _small_table_threshold 参数


这次 需要查询 Oracle 数据库 的隐藏参数, 可以建立 视图 方便 查询:

从 H$PARAMETER 视图的 DESCRIPTION 列 ,我们可以 得知参数信息 :

在 测试环境, 调整 SGA 大小,计算 STT 值:

计算公式如下 :

这里隐藏 参数 “ _db_block_buffers ”, 是 在数据库实例 启动时候 自动 生成的 。早期版本 ORACLE 数据库 通过“ db_block_buffers ”参数用来 调整 BufferCache 大小 的 参数,单位是 BLOCK ,在 ORACLE 9 时代 变成 隐藏 参数, ORACLE 数据库内部的一些参数计算 仍然 可能使用到 。


验证 _very_large_object_threshold 参数


查询 H$PARAMETER视图, 参数描述 如下 , 默认值为 500 。

百度 一番 ,存在 下面 2种 说法:

1. VLOT 就是 5倍 的 Buffer Cache 大小 , 那么 这参数 存在 什么意义。

2. 单位为 MB,在当今 单表容量随便 过 TB 的 时代 , 500 MB的上限, 基本 是错误的 。


在测试环境,通过调整SGA的大小,开启跟踪测试VLOT计算值 :

通过计算得知,其单位应该为百分比 , 计算公式如下:


相 关参数_serial_direct_read


查询H$PARAMETER视图,该参数决定是否使用直接路径读,相当于总开关


参数_direct_read_decision_statistics_driven


查询H$PARAMETER视图,参数描述如下 :

ORACLE 采用表上统计信息来决定是否使用 DPR ,而不是 DBA_SEGMENTS 里面真实记录数。该参数在 ORACLE 11.2 .0.2 以后版本默认为 TRUE 。


所以直接修改表的统计信息,可以直接影响的DPR的选择 。


测试执行 DPR 规则


测试环境: ORACLE 11.2.0.4 + Linux

开启跟踪

建立测试表 隐藏参数查询视图 系统参数 计算各个阈值 收集统计信息

修改统计信息 测试结果汇总: 可以看到在 11.2 版本下,小于 SST 不走 DirectRead ,大于 VLOT 一定走 DirectRead ,介于 SST 和 VLOT 的表,需要考虑是否为本地表或者压缩表 MTT 在 11.2 版本已经淘汰。


DPR  算法总结


Oracle 11.2版本,全表扫描或者索引快速全扫描,是否走直接路径读,与STT和VLOT值有关

总结出执行规律:


参数验证


回到 案例中,为什么在 AIX环境下选择了直接路径读,而Linux环境选择 进入 Buffer Cache 缓存;


该SQL语句采用对索引PK_TAB1进行Index Fast Full Scan,这边我列举出2套环境各个参数的真实值,并且开启跟踪验证了VLOT计算值 ;

IX 环境 :索引 大小 94716MB   >   VLOT 大小 39920MB

Linux环境 :索引 大小 94632MB  <   VLOT大小160040MB

 

这下终于搞清楚真相了,因为Linux环境的Buffer Cache内存配置较大,小于VLOT大小,所以不执行Direct Path Read;而在AIX环境下,Buffer Cache内存配置较小,超过了VLOT大小,所以执行Direct Path Read 。


四、问题延伸


分区表如何计算


前面我们已经知道普通表或者索引的VLOT算法和DRP选择机制,那么如果是分区表,ORACLE怎么进行选择呢?

测试环境: ORACLE  11.2.0.4 + Linux

相关系统参数

计算各个阈值

收集统计信息

通过不断 的修改 表 的 统计信息, 进行测试验证

测试结果汇总 :

可以看出 DPR 的评估,不会考虑分区的格式,只是取整个分区表的统计信息

如果 将每个分区的 BLOCKS 修改到最大值,表级别的 BLOCK 修改为较小值, 会出现什么情况?

重复刚才的测试,发现其执行规则没有发生改变。分区级别的统计信息不会影响 DPR 的判断 。


索引快速全扫描如何计算


测试环境: ORACLE  11.2.0.4 + Linux;

建立测试表, 4 个 HASH 分区,建立普通索引;

修改索引的统计信息

再次查询索引统计信息

确认执行计划走上 IFFS

测试结果汇总:

可以看出DPR在评估IFFS时候不会考虑STT参数。超过VOLT大小,就走直接路径读,也就是说EVENT 10949 与索引快速全扫描无关 。

新版本改进

+

+



思考一个问题,为什么很多客户的ORACLE数据库中,EVENT 10949变成必调参数?


个人见解:理想情况下,OLTP系统中大于2% Buffer Cache的表,应该大部分会走索引扫描,偶尔一两次大表全表查询走直接路径读,这样可以让Buffer Cache中的内容保持稳定,提高Buffer Cache的命中率;


但是很多客户都遇到过,开发商没有建立合适的索引,导致SQL查询走上全表查询,同时该SQL执行较为频繁,没有Buffer Cache做缓冲,大量高并发的直接路径读很容易将一台存储压垮,导致业务系统出现严重的性能问题。


可是设置了10949一定有益吗?经常进行大表全表扫描,可能拉低的Buffer Cache的命中率,也会影响其他SQL语句的执行效率;并且全扫描的问题一直被忽视,不容易被发现。


除了对问题SQL进行优化,还有没有其他方法解决?在ORACLE 12.1.0.2 引入了Automatic Big Table Caching (ABTC)为功能,数据库将Buffer Cache中的一部分划分为大表缓存,并且统计哪些大表或者索引的热度,将其存放到ABTC中,避免了频繁的Direct Path Read。

+

+



ABTC测试


在 RAC 环境中启用 ABTC 前提条件是参数 parallel_degree_policy 设置为  AUTO 或 ADAPTIVE 。


在单机环境,不依赖 parallel_degree_policy 参数;


配置ABTC参数,同时需要确认force_full_db_caching是关闭的

配置参数db_big_table_cache_percent_target,为ABTC占Buffer Cache的比例,最大值为90

该 特性存在 2张相关视图:

视图v$bt_scan_cache统计ABTC的使用情况,里面MEMORY_BUF_ALLOC列显示消耗CACHE的大小

视图 v$bt_scan_obj_temp s存放 ABTC中对象信息 ,可以查询到ABTC中缓存表信息, TEMPERATURE 列 , 描述 对象的 热度。每执行一次全表扫描,TEMPERATURE列值加1000。

POLICY 列 , 显示对象在 ABTC中的状态 : MEM_ONLY 、 MEM_PART 、 DISK 、 INVALID

在大内存环境中,配置了ABTC后,当表大小超过STT时,不会执行直接路径读,而是进入ABTC中进行缓存,这样就可以节省很多物理IO 。


总结:

小型机迁移至X86平台是行业大趋势。迁移过程评估平台优缺点、性能差异、迁移方案、维护成本等因素;不仅需要全面的知识,更需要参考业内成功案例,不妨联系中亦科技,帮您达成目标!

本文转载于中亦安图

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31547066/viewspace-2283750/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
性格开朗,有较强的学习能力,对oracle数据库的体系结构,搭建RAC,timesten,goldengate,分布式数据库,dataguard,系统调优有较深入的了解, 尤其是oracle优化,深入学习的主机命令,对数据库的优化,SQL语句的优化有深入的认识,目前正在shell脚本,mysql,以后会有计划学习大数据和python。

注册时间:2018-07-23

  • 博文量
    200
  • 访问量
    475047