解决Logical Reads高的方法和实验
2017-08-01 22:16
232 查看
之前介绍了CBC,就是cache buffer chains这个等待事件的影响,《缓解latch: cache buffers chains的案例》,解决逻辑读过高的SQL语句,是优化方向。为了更直观地说明这个问题,通过模拟实验,来了解下。
创建测试表,test表三个字段,分别是id1,id2和name,insert入100万行记录,其中id1每个distinct值100次,id2针对每个id1的distinct值,其是唯一的,namedbms_random则是取随机数,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkyMIhTpsIriaDMBM1HlFgjNVFicgovW8PzlH0VuQdfZInjWr3ler38E4w/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
test表总计为127MB,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkObsHlnvPDmmrOPu4GnpPPdm112c6XDgycIl5TOVgFEh7y4PnIzEzlQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
新建test表id1字段,为非唯一单键值索引,收集表的统计信息,cascade=true,这张表每行平均占用字节108个,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwknFge6zA7Rsns0bia56NnVklQibicM5xyicIudLWu4zvEP7ic7jB9DXibm4Vw/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
根据id1=1、id2=746,以及name的取值执行SQL,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkgIzNjNwkNricoYNUL90Jb1DkibAXgMtQUOicoZWEr3ZTS1gEDextSaeSQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
执行计划中,E-Rows和A-Rows一样,第一步是根据id1索引检索符合条件的rowid键值,根据数据特征,会返回1万条记录,需要回表,根据id2和name字段,过滤检索,返回符合条件的1条记录。相应内存消耗181,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkNQLHHEWXnpFiaURohzOJsqiaxHRIRPvqnvyw0icQLqhddsEt7Ykicz3pmw/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
删除原索引,新建id1和id2的复合索引,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkGicLgia8TKf7ficds6GqhibC7kDDOe0h1kgwtu2eOna0xVB33x0hhoGzQA/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
执行同一条SQL,E-Rows和A-Rows一样,第一步会根据id1和id2的复合索引,检索出1条记录的rowid,第二步回表检索这个rowid,对应的数据,根据name过滤条件,返回检索。相应内存消耗5,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkrbw5JXCYXvGDunyFLiboAuSxYhnSV3Dkic8LZKic1XrM0MlscjgQUZ4xQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
内存消耗之所以下降了,就是因为从数据特征看,id1、id2和name条件检索结果只会是1条记录,但id1索引会返回1万条数据,在此基础上,做过滤处理,相当于要将1万条数据加载至buffer cache,108bytes(单行平均长度)*10000条=1MB,即一次执行需要1MB的数据内存空间,而id1和id2的复合索引,从索引扫描阶段,就只会返回唯一一条记录,根据name过滤处理,需要的数据空间为108bytes(单行平均长度)*1条=108bytes,即一次执行需要108字节数据内存空间。
我们从AWR看下两种索引的区别,
(1) id1这个单键值非唯一索引,两个session,并发总计执行20万次select操作,基本需要10分钟所有的时间,逻辑读消耗5万次/秒,每次交易消耗逻辑读21万,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkiakdqZJXUdVGrWftlMfGWhAKOG5feKjCYo2cMS2Bp1IXvqSozbicyrbQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
SQL ordered by Gets中则显示这条SQL逻辑读消耗,排名第一,每次执行消耗179次逻辑读,执行20万次,总计消耗3千5百万次逻辑读,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkibbyoRalNOQC1pCzpHOX65gw72oxiaUOhBZItlj6p48yyMWib5uQtNA9Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
(2) id1和id2复合索引,两个session并发执行总计40万次select操作,基本每20万次执行之需要1-2秒,逻辑读消耗1万9千/秒,每次交易消耗逻辑读2万次,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwklT55IW5aLEq3a9EK8OL18kAZEpWXibd0F0aCGpsIOUGr6zbz1tQfibXw/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
SQL ordered by Gets中则显示这条SQL逻辑读消耗,排名第一,但每次执行仅消耗4次逻辑读,执行40万次,总计消耗160万次逻辑读,执行次数翻了一倍了,但逻辑读消耗仅为原来的1/21,自然支持的TPS就会提升了,
![](http://mmbiz.qpic.cn/mmbiz_png/a1q64ic86PakIoicahiaicqn5rH9ZczoSHwkzptImoecMcCwnGwUOKeUKG1Egm5dhKnsGlzLCJetmC6qKfXZP9rucg/640?wx_fmt=png&wxfrom=5&wx_lazy=1)
总结:
1. CBC等待事件,结合Load Profile中的逻辑读部分,往往需要关注SQL ordered by Gets中排名靠前的SQL语句,如何使这些SQL语句逻辑读降低,是优化方向。
2. 可能需要分析SQL执行计划,看是否实际执行,加载了本不需要的内存,索引设置是否合理了。
3. AWR、SQL AWR这些工具,均是我们的利器,要充分利用这些。
如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)
创建测试表,test表三个字段,分别是id1,id2和name,insert入100万行记录,其中id1每个distinct值100次,id2针对每个id1的distinct值,其是唯一的,namedbms_random则是取随机数,
test表总计为127MB,
新建test表id1字段,为非唯一单键值索引,收集表的统计信息,cascade=true,这张表每行平均占用字节108个,
根据id1=1、id2=746,以及name的取值执行SQL,
执行计划中,E-Rows和A-Rows一样,第一步是根据id1索引检索符合条件的rowid键值,根据数据特征,会返回1万条记录,需要回表,根据id2和name字段,过滤检索,返回符合条件的1条记录。相应内存消耗181,
删除原索引,新建id1和id2的复合索引,
执行同一条SQL,E-Rows和A-Rows一样,第一步会根据id1和id2的复合索引,检索出1条记录的rowid,第二步回表检索这个rowid,对应的数据,根据name过滤条件,返回检索。相应内存消耗5,
内存消耗之所以下降了,就是因为从数据特征看,id1、id2和name条件检索结果只会是1条记录,但id1索引会返回1万条数据,在此基础上,做过滤处理,相当于要将1万条数据加载至buffer cache,108bytes(单行平均长度)*10000条=1MB,即一次执行需要1MB的数据内存空间,而id1和id2的复合索引,从索引扫描阶段,就只会返回唯一一条记录,根据name过滤处理,需要的数据空间为108bytes(单行平均长度)*1条=108bytes,即一次执行需要108字节数据内存空间。
我们从AWR看下两种索引的区别,
(1) id1这个单键值非唯一索引,两个session,并发总计执行20万次select操作,基本需要10分钟所有的时间,逻辑读消耗5万次/秒,每次交易消耗逻辑读21万,
SQL ordered by Gets中则显示这条SQL逻辑读消耗,排名第一,每次执行消耗179次逻辑读,执行20万次,总计消耗3千5百万次逻辑读,
(2) id1和id2复合索引,两个session并发执行总计40万次select操作,基本每20万次执行之需要1-2秒,逻辑读消耗1万9千/秒,每次交易消耗逻辑读2万次,
SQL ordered by Gets中则显示这条SQL逻辑读消耗,排名第一,但每次执行仅消耗4次逻辑读,执行40万次,总计消耗160万次逻辑读,执行次数翻了一倍了,但逻辑读消耗仅为原来的1/21,自然支持的TPS就会提升了,
总结:
1. CBC等待事件,结合Load Profile中的逻辑读部分,往往需要关注SQL ordered by Gets中排名靠前的SQL语句,如何使这些SQL语句逻辑读降低,是优化方向。
2. 可能需要分析SQL执行计划,看是否实际执行,加载了本不需要的内存,索引设置是否合理了。
3. AWR、SQL AWR这些工具,均是我们的利器,要充分利用这些。
如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)
相关文章推荐
- make: Nothing to be done for `all' 解决方法 ---实验2
- NIOS II 学习第一天:LED流水灯实验中诸多困惑的解决方法
- 嵌入式Linux开发实验中遇到的问题及解决方法
- Ubuntu 14.04源码安装qemu实验例程-问题-解决方法分享
- 解决IP地址冲突的方法--DHCP SNOOPING 经实验
- 实验中可能出现的错误及其解决方法
- 数据库实验中遇到的问题以及解决方法
- TCP+UDP通信实验的设计思路及所遇问题的解决方法
- 在交付的实验环境中对许可证过期问题的虚拟机关机问题的解决方法 推荐
- VPC安装LINUX后花屏的解决方法(我实验过,可以用的)
- 总结NFE板卡实验中遇到的问题和解决方法
- 〖Windows〗zigbee实验之cygwin编译TestSimpleMac出错的解决方法
- 解决IP地址冲突的方法--DHCP SNOOPING 经实验,使用效果非常好
- 防火墙技术在实验网络安全中的解决方法
- 阅读《第一行代码》,接收短信实验时,SmsMessage类deprecated过时的原因和解决方法
- 虚拟IP实验,遇到场景启用使用虚拟IP就报错,不启用可以正常运行的问题,解决方法
- make: Nothing to be done for `all' 解决方法 ---实验2
- μC/OS-II实验:实验二 优先级反转及解决方法
- "右键发送" 造成死机,解决方法,实验管用
- Http 403错误重现实验及解决方法