作者文章: Fenng

TOP 第五章 之 CBO配置策略

继续贴出 Troubleshooting Oracle Performance 一书第五章《配置查询优化器》的翻译稿的部分节录。本章初稿译者胡怡文.

配置还是不配置

在此套用一句肯尼亚谚语 ,”配置查询优化器的代价是昂贵的,但值得为此付出。”(注1)实际上,我曾见过许多低估良好配置重要性的站点。有时,我甚至和一些人进行激烈的讨论,他们认为”没有必要费心为每一个数据库单独配置查询优化器,我们已经有一套初始化参数,而且在所有数据库上屡试不爽。”通常,我首先会这样回答这个问题:”如果一个配置集能适用于所有数据库,为什么Oracle要介绍二十多个专用于查询优化器的初始化参数?甲骨文公司知道自己在干什么。如果存在这样一个万能的神奇配置,他们会以默认的方式提供,还可以省去一大堆初始化参数的正式说明文档。”接下来我会详细解释这个神奇配置不存在的原因:

  • 每个应用都有自身的需求和负载概要,并且
  • 每一个由不同的软硬件构成的系统,都有其自身的特点。

如果遇到麻烦的是顾客,通常我也会提醒他们”您找我是因为你遇到性能上的问题,对吧?由于某种原因,应用没有达到最佳表现,但数据库也得为目前的情况负一部分责任…所以,让我们着手处理这个问题吧。”

据说,至少从Oracle9iR2开始,查询优化器就能良好运转了,这意味着它能够为大多数注2SQL语句生成高效的执行计划。然而更准确的说,仅在查询优化器配置正确且数据库的设计能够发挥其所有特性时才是如此。这件事我已再三强调,同时也要记住查询优化器的配置不仅包括初始化参数的设置,也包括系统统计和对象统计。

配置路线图

既然没有这样的神奇配置,就需要一个可靠的步骤来帮助我们。图5-1汇总了我采用的主要步骤。

CBO_Configure.png
图5-1. 配置路线图的主要步骤
下面是对图中标有数字的步骤的描述

  • 1. 总是需要调整的两个初始化参数:optimizer_mode和db_file_multiblock_read_count。 就如你将在本章后面看到的那样,后者对查询优化器本身来说已经不再那么重要。然而,个别操作的性能还将严重依赖它。
  • 2. 这步要调整的几个初始化参数通常默认已经被设置为比较合适的值,所以这步显得不是十分重要。然而无论如何,这一步的目的是要启用或禁用查询优化器的某些特性。
  • 3. 既然系统统计和对象统计为查询优化器提供了至关重要的信息,那么它们必须被收集。
  • 4. 根据初始化参数workarea_size_policy的不同,在内存中存储数据时选择是手动还是自动调整内存的使用量。做出选择后,其它初始化参数值在第五步或第六步设置。
  • 5. 如果上面选择的是自动设置工作使用的内存量,那么需要设置初始化参数pga_aggregate_target。
  • 6. 如果选择手工设置的话,实际使用的内存量分别取决于对每一种不同操作所设置的阀值。基本上,对每一种不同的操作都要设置一个特殊的初始化参数。
  • 7. 当刚才的设置生效后,就开始测试应用。在测试期间,对没有表现出期望性能的那部分收集执行计划。通过分析执行计划,你应该能够推测出问题所在。本阶段需要注意,关键是要识别出一般的、非特殊的现象。比如说,需要注意查询优化器是否使用了过多或过少的索引,又或是否没有正确识别约束。
  • 8. 如果查询优化器能够为大多数SQL语句提供高效的执行计划,说明配置成功。否则,需要进行第九步。
  • 9. 假如查询优化器倾向于使用过多或过少的索引,又或是嵌套循环的话。通常需要调整初始化参数optimizer_index_caching和optimizer_index_cost_adj修正这个问题。如果查询优化器错误地估计了基数(cardinality)。有可能是某些直方图丢失或需要调整。在Oracle 11g中,扩展的统计(extended statistic)也能够提供一些帮助。

根据图5-1,从第1步到第6步设置的初始化参数不宜改变。当然,这也不是铁板钉钉的。如果在第九步调节了索引相关的初始化参数和直方图后,还没有达到预期的效果。就有必要从头再来了。还有一点要提一下,既然有些初始化参数的设置对系统统计有影响,在调整它们以后,必须重新计算一下系统统计值。


  • 注1:那句肯尼亚谚语是”和平的代价是昂贵的,但值得为此付出。” 可以在http://www.quotationspage.com/quote/38863.html. 找到这个引用。
  • 注2:和我们在其它可想像的活动中一样,在软件开发中完美也是不可信任的。即使你和Oracle都不希望这样,查询优化器也是如此。因此,应当期盼只有少数的SQL语句需要手动调整的介入(这个话题放在第七章)。

EOF

此文作者:, 位于 Database 分类 标签: on .
转载须以超链接形式标明文章原始出处和作者信息及版权声明.

TOP 第四章 之 保持统计信息时效性的策略

继续贴出 Troubleshooting Oracle Performance 一书第四章《系统和对象统计信息》的翻译稿的部分节录。在前面几章的部分章节放出来后,收到了很多朋友的意见和建议,在此一并谢过!翻译更多是考量译者的中文水平,现在我们几位译者对此是深有体会。本章初稿译者朱一(@mujiang)


保持统计信息时效性的策略(Strategies for Keeping Object Statistics Up-to-Date)

工具包dbms_stats提供了很多管理对象统计信息的功能。那么我们该如何使用它来达到最佳配置呢?这个问题很难回答。很可能就没有确定的答案。就是说,没有一种方式适用于所有情况。让我们研究一下该如何着手解决这个问题。

基本准则是,或许是最重要的一个,查询优化器需要通过对象统计信息知道数据在数据库里面是如何存储的。因此,修改数据以后,同样需要刷新对象统计信息。我提倡定期收集统计信息。反对者的理由是数据库运行好好的,没必要重新收集统计信息。这种策略引起的常见问题是,一些对象统计信息依赖于实际存储的数据值,比如修改了最大/最小值,这样的修改不会经常发生在一些典型的表里面,但是这些数据改变是危险的,它们被应用程序频繁的使用(引用过时的统计信息)。实践当中,太多的问题是因为对象统计信息过时引起的。

显而易见,反复收集静态数据的对象统计信息是没有意义的。只应该对统计信息陈旧的对象进行收集。所以,需要利用好每张表的修改次数的统计记录。这样,我们只需要收集哪些数据发生了显著变化的表的统计信息。默认情况下,当一个表里面有超过10%的行被修改后,就认为它的统计信息是过时的(陈旧的)。缺省值就不错,在Oracle 11g以后,这个缺省值可以修改。

收集统计信息的频率也值得探讨。从每个小时收集到每个月,或是更少,均看到过成功案例。其实这个真的依赖于数据。当用并不陈旧的表统计信息作为基准时,太长的时间间隔引起过多表的统计信息陈旧,就要花更多的时间收集统计信息。因此我喜欢收集得稍微频繁一些,分散负载,尽量缩短每次收集任务的时间。如果你的系统每天或每周有一些时段负荷比较低,就在这些时段运行计划的收集作业。如果你的系统是真正的7×24的系统,最好频繁的运行收集任务(注),每天运行多次,尽量多分散负载。

如果有好的理由不需要收集一些表的统计信息,在Oracle 10g以后,可以锁定对象统计信息。计划收集作业就会跳过这些对象。这样远远好于禁止收集整个数据库的统计信息。遗憾的是,在Oracle 9i中不能锁定对象统计信息,变通方法是,利用表的监控属性,禁止这些不需要收集统计信息的表的监控,收集模式(schema)或者数据库的统计信息的作业就会跳过这些表。

如果你有批处理任务一次加载、修改很多数据,干脆不要等待调度任务来收集这些对象的统计。直接将对这些对象的收集统计任务加到批处理任务的最后面。也就是说。如果你知道一些表的数据会被大量修改。修改完数据后,立刻收集对象统计信息。

从Oracle 10g开始,应该尽可能的利用默认的收集作业。为满足需求,应该进行检查默认的配置,如果必要的话,进行必要的变更。既然只有Oracle 11g以后可以在对象级别配置收集任务,你可以在缺省收集作业之前运行自定义的作业以收集一些有特殊需求的表的统计信息。这样,缺省收集作业仅操作统计信息过时的表,跳过有特殊需求的表。锁定特性也可以确保只有特定的收集作业才可以重新收集那些关键表的统计信息。

如果收集统计信息导致了低效的执行计划,有两个办法。一是恢复以前合适的统计信息来修复问题。二是诊断查询优化器为何使用新收集的统计信息得出了低效的执行计划。首先要检查统计信息是否正确的描述了数据的分布。比如,采样新的数据分布得到了不同的直方图。有可能是收集本身,或者是收集用到的一个参数的问题,导致了坏的统计信息。如果统计信息是可信的,有两种可能导致低效的执行计划:错误的配置了查询优化器,或者优化器犯了一个错误。对于后者我们无能为力,而对于前者,我们能找到解决办法。无论如何,你应该避免仓促的下结论,推断说是收集统计信息引起的问题,进而停止收集统计信息。

最佳实践是使用工具包dbms_stats收集对象统计信息。然而,有些情况下,正确的对象统计信息反而误导查询优化器。有一个常见的案例,比如历史数据必须保留很长一段时间(比如有些类型的数据在瑞士必须保留十年),如果随着时间的推移,数据分布基本不变,用工具包dbms_stats收集对象统计信息会运行良好。相反,如果每个时期有不同的数据分布,应用程序仅仅使用全部数据的一个子集,那么手工修改统计信息使它反映最相关的数据就是明智之举。换句话说,如果你知道工具包dbms_stats忽略了或者不能发现最相关的数据分布,告诉查询优化器回避对象统计信息就是恰当的。


注:对此,译者有不同的观点。对于比较繁忙的在线系统,数据变化可能频繁,但数据特征的变化未必频繁。不管如何,频繁收集统计与否,DBA 必需熟知两种可能带来的影响。(译者注)

EOF

九十年前的今天,是个特殊的日子。

Twitter每日推荐一位推友计划 (第一季)

按:在几个月前,我在Twitter上发起了一个试验性的计划:每日推荐一位推友计划 。最初是因为 Blogkid 友情帮我做了点事情,所以友情推荐了他一下,继而忽发奇想,何不以此为契机,做个实验呢? 说干就干。倒没想到一发不可收拾。基本上一段时间下来,每个被推荐人的订阅数都有了不小的增长,而且继而又能从他们那里多看到一些好玩的内容,甚至自己的 followers 也有了很大增长(将近3000 ),互惠,多赢。

有趣的是,网易有篇新闻,引用的图中心节点居然是我…

废话说完,简单说说说一下我推荐原则(逐渐摸索中清晰化的):

  • Twitter 背后的那个人在某个领域要有一定影响力或者有趣或是 Twitter 内容比较有价值。
  • 订阅人数(followers)不超过 500 个才可能会加入推荐候选列表。如果订阅者少于100,基本发现很难形成良性互动,有的新用户就会意兴阑珊–毕竟自言自语不是很有意思的事情。而一旦超过200,就基本到了一个比较良性的循环了。对于超过500的,基本上不用推荐也会自然增长,边界效益不高。
  • 非商业行为。同时避免侵犯隐私,每个人的介绍以网络可以搜索到的为准。
  • 在每个工作日进行推荐,一般在下午 15:00 左右,这个时间也是公司下午茶时间,基本不影响工作。

如果要跟踪这个推荐计划,请 follow 我(@Fenng ). 第一季推荐的人见下面列表(按照时间排序)。介绍语基本上都是我拟就的,如果有不合适之处,那肯定是我没说好。


  • @Blogkid
    张磊,Geek,创建过 Niupu.com 。目前即将学业有成,准备赴京陪伴女友,顺便工作,风闻海内外各互联网公司纷纷竞聘云云…
  • @izlmichael
    张亮, Apple4us 创建人, 《环球企业家》杂志记者, 他的很多文章让我受益颇深.
  • @wingoffire
    王皓(aka.南瓜), 虾米音乐网(xiami.com)创建人, 前摇滚乐队乐手, 阿里黑帮之一 .
  • @zhaozexin
    赵泽欣(aka. 小马), Taobao UED 前端技术专家(相当嘀牛). 也是 JobsDigg 热心用户. 补充:最新译作《JavaScript语言精粹》已经上市…
  • @taiwen
    霍泰稳, InfoQ 中文站主编(搞 Java 的都知道 InfoQ!)…
  • @Tinyfool
    郝培强, 银杏泰克科技有限公司共同创始人, Geek ,乐高积木爱好者.身材有我两个壮,技术至少也是我的 200% .
  • @virushuo
    霍炬, 银杏泰克科技有限公司共同创始人. 提供搜索引擎技术服务解决方案, Geek , 双截棍爱好者. 技术至少也是我的200% .
  • @zhengyun
    郑昀, 玩聚网创建人, 语义应用探索者.玩聚 SR: http://SR.ju690.com/ 挺好玩. 他最近怎么和月光打起来了? 止戈…
  • @CloudWu
    云风[说明: 标签中遗漏, 但对他不需要多介绍. ]
  • @Livid
    Livid. [说明: 标签中遗漏, 但对他也不需要多介绍. ]
  • @robbinfan
    范凯, JavaEye创建人, 在数个技术领域(Java/Ruby/Web…) 都是牛人. 对 SNS的系列大作让人耳目一新.
  • @nowazhu
    Nowa, Web 前端技术开发高手,来自前阿里妈妈技术团队(现淘宝).苹果产品超级粉丝.iPhone 专业破解达人.
  • @gofeeling
    刘平阳, 前 Yupoo! 创始人.现在重新出发,潜心做新项目中… 另:通过虾米网点首歌送给平阳:刘欢的《从头再来》…
  • @flycondor
    耿新跃, 豆瓣技术总监,负责豆瓣开发过程方面内容.也是 DB 技术高人.他也是豆瓣员工中少数在 Twitter 上活跃的用户…
  • @twijean
    陈俊,《东方企业家》高级记者[现在变化了]. 上海 5G 活动组织者之一. 他的 blog 地址: http://www.jeanchen.net/
  • @digitalboy
    张扬(@digitalboy ) Geek 商店创建人, 出售各种稀奇古怪的小玩意儿 http://geekcook.blogspot.com/
  • @hongqn
    洪强宁, 豆瓣首席架构师,负责豆瓣技术架构方面内容..他将在即将举行的 QCon(北京)的会议上分享豆瓣的架构经验…
  • @sky000
    简朝阳, 来自阿里B2B的DBA团队,小伙子不止在 Oracle 方面经验丰富,还对 MySQL 有深入研究, 他的 MySQL 新书《MySQL 性能调优与架构设计》即将上市.
  • @JunChen
    吴隽辰, 途牛网设计总监.资深驴友.设计师,Blogger,UCDChina发起人. 值得一提的是,发型也超酷无比,堪称非主牛代表.
  • @hellodba
    张瑞, 看 ID 就知道是个 DBA , 来自阿里B2B的DBA团队. 比我资深多了,讲究生活品质,物质、精神层次两手抓.[补充:最近一篇关于数据中心的大作传遍江湖.]
  • @accesine
    田春峰,早期关注搜索技术,搜房的,现在对 SEO 很专注,他的Blog 名叫做”我想去桂林”,不知道他是否已经有时间去过桂林了.
  • @LinuxToy
    LinuxToy.org, 原因只有一个--LinuxToy.org 这个站点内容的确不错.
  • @erning
    张尔宁, 曾是 eBay CDC 资深架构师,安居客创建人之一.其实, erning (二宁)就是一宁的弟弟,兄弟俩都热心公益事业.
  • @wangpei
    王佩, 当年互联网四大杀手之一: 红心杀手. 他现在的活动据点:http://www.baibanbao.net/ . 我和他同在杭州,居然去年在广州网志年会才见面一次.王佩缠着绷带参加年会,给我印象最深了,哈.
  • @mranti
    安替, 自由撰稿人,新闻研究人. 纵横周刊创建人. 去年中文网志年会主题演讲就是他.其实关于他是谁可能不需要介绍了.
  • @aleksoft
    Alex.Mou博士,做啥网(zuosa.com)的创建人. Twitter 上也有不少做啥的用户,使用有问题,给他拍砖!
  • @yudunde
    于敦德,途牛网(tuniu.com)创建人之一. 要旅游,找途牛.老于也是技术人,当年分析 LiveJournal 架构的文章流传颇广.
  • @hzsijian
    思践, 虾米网创始人之一, COO. 是阿里创业黑帮代表人物. 在电子商务圈非常有影响力.
  • @mijia
    米嘉,Firefox 中国的工程师. Geek. 如果你是 Firefox 的粉丝,或许从他那里能看到很多小道消息.
  • @belltoy
    赵钟秋, 出色的 LAMP 技术人员,沟通能力值得称赞.对”Web技术和开源技术感兴趣,有强烈的热情”, 刚刚友情帮 JobsDigg 解决了一个技术问题. 另请移步访问:http://belltoy.cn/
  • @dreamwords
    孟岩, 此孟岩不是CSDN那个,而是财帮子创建人之一. RoR 高手.曾供职于 Sun、微软.
  • @gongjun
    梁公军,鲜果网(xianguo.com)创始人.坚持将 RSS 普及到底的家伙.
  • @turen
    谭晓生, Myspace 中国区CTO,前阿里巴巴-雅虎中国技术研发部总监.
  • @Alipay
    支付宝(@Alipay). 考虑到今天日子比较特殊(注:04.01).所以推荐一个非官方的虚拟角色吧.当然 @Alipay 背后也是实在的人(不是机器人).有些我不方便说的,会在这里体现.
  • @dashhuang
    黄一孟, VeryCD.com 的创始人啦,年轻有为.Twitter 上的绝大部分朋友都用过他们的服务了吧? 不多介绍,等 dash 同学自己推消息吧.
  • @turingbook
    刘江, 图灵图书主编.是IT出版界的奇才之一(另一位下回介绍),目光如炬.当年在电力引入的那批书至今仍有余威,更别说近年来的图灵系列了.
  • @yurii_yusheng
    余晟,前抓虾主程,现银杏泰克主程,奥地利经济学派著名著作《权力与市场》译者,《精通正则表达式》译者,即将出版的《技术领导之路》译者.
  • @guojiayue
    郭家悦, 美空网( http://moko.cc/ ) 联合创始人. 美空网的美女密度是国内所有网站最高的.如果要美空注册账户,可以follow @guojiayue 同学,给他提建议/意见.
  • @yining
    张一宁, Blogger, 标准Geek, 公益事业积极参与者. @erning 他哥. 另请访问他的Blog:http://www.yining.org/ 近期更新不多.
  • @xiaolai
    李笑来, 原新东方托福阅读老师,现艾德睿智国际教育咨询合伙人,乐于分享,博文很赞(http://www.xiaolai.net/) 时间管理著作《把时间当作朋友》即将出版
  • @lancelot23
    且听枫吟, 比较陌生? 他就是Leica中文摄影杂志(http://www.leica.org.cn/)的运营者啦.他也是一位资深媒体人,现在某媒体集团做Online Marketing
  • @bryanzk
    郑柯,《程序员》杂志 高级编辑. InfoQ 也有不少翻译的技术文章出自他的手笔. 要给《程序员》投稿找他再合适不过.
  • @lusoo
    程立, 支付宝当之无愧的首席架构师(没有之一).
  • @xmpp
    杨卫华, 英文名Tim Yang, 在新浪搞UC的技术架构工作,对XMPP(Jabber)及开放IM架构经验非常丰富 他的Blog: http://timyang.net/ (后端技术)一定要看
  • @ningoo
    宁海元,淘宝网资深DBA, Oracle、MySQL、OS 方面功力深厚(以后猎头都别来挖我了,挖他吧),他的Blog: http://ningoo.net/
  • @huairen
    坏人,工作过”北上广深杭”,被戏称”交友行业之父”,曾任职”世纪佳缘””百合网””珍爱网””嫁我网”产品部,参与多次改版,后上海”篱笆网”产品部.现淘宝UED创新产品.交互和营销,产品项目方面号称略懂.

最后再附加两个好玩的:


按照我的本地记录,这是目前推荐过的列表. 感谢网友 Ivan Chen(@fireshort),另请参见他整理了列表,不过我不赞同他的那个帖子的题目。

敬请期待第二季…

现在连岳也开始现身Twitter(@LianYue),有理由相信他会成为中文Twitter之王。原因? 不说你也知道。

Updated: 你可以批量跟随: TweepML 。(使用前请注意安全性。)

此文作者:, 位于 Geek 分类 标签: , on .
转载须以超链接形式标明文章原始出处和作者信息及版权声明.

TOP 第二章 之 绑定变量

继续贴出 Troubleshooting Oracle Performance 一书第二章《关键概念》的翻译稿的部分节录。昨天贴出第一章的部分内容,收到不少朋友的反馈,坦诚的讲,第一章多半是通用知识,和 DB 相关的信息并不是很多,这次再看看第二章的(借口归借口,问题还是要改正)。必须要说明的是,此书翻译并非兄弟我一人之力。译者包括:童家旺、胡怡文、冯大辉(出版顺序),还有海外华人朱一和青年才俊张磊两位的劳动成果。如果留言有问题,请在 Twitter 上给我反馈也可: @Fenng

TOP.jpg
(此书中文名字还未敲定)


绑定变量

绑定变量通过两种方式来影响应用。第一,从开发的角度看,它使得开发或者变得简单,或者是变得更加困难(或更精确地讲,需要更多或更少地编码)。既然这样,具体的效果就取决于用来执行SQL语句的应用程序接口(Application Programming Interface, API)。例如,如果是使用PL/SQL来编码,使用绑定变量来执行就会更加简单。另一方面,如果是使用JDBC(Java Data Base Connectivity)来开发,不使用绑定变量来执行SQL语句则会更加简单。第二,从性能的角度看,绑定变量既有优势也有劣势。

注意:你将会在下面的内容中看到一些执行计划。第6章将会介绍如何获取并解释执行计划。如果有什么不清楚的话,可以考虑稍后返回本章。

2.5.1 优势

绑定变量的优势是可以在库缓存中共享游标,这样就可以避免硬解析以及与之相关的额外开销。下面内容是运行脚本bind_variables.sql的结果,它展示了三个INSERT语句由于使用绑定变量而共享了库缓存中的同一个游标的情形。

SQL代码, 略.

可是,也有一些情况下,即使使用绑定变量也会产生多个子游标。下面的例子就展示了这种情况。注意,INSERT语句与前面例子中的完全一样。只有对应的VARCHAR2变量的最大长度发生了变化(从32变成33了)。

SQL代码, 略.

之所以会创建新的子游标(子游标1),是因为相对于最初的3个INSERT语句来讲,第4个INSERT语句的执行环境发生了变化。 这个不匹配可以通过查询视图 v$sql_shared_cursor 来得到确认,是绑定变量的原因。

SQL代码, 略.

这是由于数据库引擎应用了绑定变量分级(graduation)。这个功能的目的是为了最小化子游标的数量,它是根据绑定变量的长短将绑定变量(各个大小不同)分为四个级别。在32个字节以内被分在第一个级别,33到128个字节的被分在第二个级别,129到2000个字节的被分在第三个级别,其余的大于2000个字节的被分在第四个级别。NUMBER类型的绑定变量被分在它的最大长度22个字节上的级别上。从下面的例子可以看到,视图v$sql_bind_metadata显示了级别的最大长度。注意,即使在子游标1的变量长度只有33的时候,也是使用最大长度为128的级别。

SQL代码, 略.

系统不要求每次生成子游标的时候都生成一个新的执行计划。新的执行计划是否与另一个子游标使用的执行计划一致,也依赖于绑定变量的值。这将在下面的内容中进行介绍。

2.5.2 劣势

在WHERE从句中使用绑定变量的缺点是会有一些至关重要的信息对查询优化器不可见。事实上,对查询优化器来讲,使用直接文本要比使用绑定变量来的更好。使用直接文本可以提高成本估算的准确性。当检查一个值是否在可用数值范围以外(也就是,小于存储在这个字段的最小值,或者大于最大值)或者是否利用到直方图(histogram)时,就更是这样了。为了展示的需要,我们准备了一个含有1000条记录的表,它的字段id的值在1(最小值)到1000(最大值)之间。

SQL代码, 略.

如果一个用户查询id小于990的所有记录,查询优化器知道(根据对象的统计信息)有差不多99%的记录被筛选。因此,它会选择使用基于全表扫描的执行计划。同时请注意,估算出的基数(执行计划中Rows字段的信息)与查询语句实际返回的记录数是否相符。

SQL代码, 略.

当另外一个用户查询id小于10的所有记录时,查询优化器知道只有大约1%的记录会被选中。因此,它会选择使用基于索引扫描的执行计划。在这个例子中,也请注意估算的准确与否。

SQL代码, 略.

只要是使用到绑定变量,查询优化器都会忽略它们的具体值。从而,前面例子中的准确的估算就不太可能会出现。为了解决这个问题,Oracle9i中引入了一个被称为绑定变量窥测(bind variable peeking)的功能。

警告:绑定变量窥测不支持随Oracle9i一起发布的JDBC 瘦驱动(JDBC thin driver)。这个限制在Metalink的注解273635.1中有记载。

绑定变量窥测的概念是比较简单的。在物理优化阶段,查询优化器会窥测绑定变量的值,将它作为文本来使用。这种方法的问题是它生成的执行计划会依赖第一次生成执行计划时所提供的值。下面这个基于脚本bind_variable_peeking.sql的例子展示了这种情形。注意,第一次优化是使用值990来执行的。结果,查询优化器就选择了全表扫描。由于游标是共享的,因此是这个选择影响了第二次使用10作为条件的查询语句。

当然,如同在下面的例子中那样,如果第一个执行计划替换成使用值10来执行,查询优化器就会选择一个基于索引扫描的执行计划-然后,就会再一次发生这两条查询语句上。注意,为了避免共享前面例子中的游标,这些语句是使用小写字母来写的。

有必要强调,只要游标还保存在库缓存中并且可以被共享,就可以被重用。不管与它相关的执行计划的效率如何,这种事情都会发生。

为了解决这个问题,Oracle11g中引入了一个称为扩展的游标共享(extended cursor sharing,也称为适应性游标共享,adaptive cursor sharing)的新功能。它的目的是在重用一个已经存在的但是会导致执行效率低下的游标时能够自动进行识别。通过查看前面例子中使用的SQL语句在v$sql中的内容,可用来帮助我们理解这个特性是如何工作的。要到Oracle11g中v$sql视图中才有下面这些字段:

  • 是否绑定敏感(is_bind_sensitive):不仅指出是否使用绑定变量窥测来生成执行计划,而且指出这个执行计划是否依赖于窥测到的值。如果是,这个字段会被设置为Y,否则会被设置为N。
  • 是否绑定可知(is_bind_aware):表明游标是否使用了扩展的游标共享。如果是,这个字段会被设置为Y,如果不是,这个字段会被设置为N。如果是设置为N,这个游标将被废弃,不再可用。
  • 是否可共享(is_shareable):表明游标能否被共享。如果可以,这个字段会被设置为Y,否则,会被设置为N。如果被设置为N,这个游标将被废弃,不再可用。

在下面的例子中,游标是可共享的并且是绑定变量敏感的,但是没有使用扩展的游标共享:

SQL代码, 略.

当游标对这个绑定变量赋不同的值执行多次以后,有趣的事情发生了。在使用值10和990执行了几次以后,视图v$sql提供的信息发生了变化。注意,0号游标不再可共享,并且产生了两个新的使用了扩展的游标共享的子游标。

查看与这个游标关联的执行计划,你可能会发现,其中一个新的子游标会使用基于全表扫描的执行计划,而同时另一个会使用基于索引扫描的执行计划:

SQL代码, 略.

有以下几个新的动态性能视图可用来进一步分析生成这两个游标的原因:v$sql_cs_statistics、 v$sql_cs_selectivity和v$sql_cs_histogram。第一个视图说明是否使用了窥测(peeking)以及对应于每个游标的相关执行统计信息。根据下面的输出,基本可以确认,对于同一个执行语句,游标1处理的记录数高于游标2处理的记录数。因此,查询优化器在一种情况下选择了全表扫描,而在另一种情况下却选择了索引扫描。

SQL代码, 略.

视图v$sql_cs_selectivity显示与每个游标的每个选择条件相关的选择性范围。事实上,数据库引擎不会为每一个绑定变量值创建一个新的游标。而是将具有同样选择性的并有可能导致生成同一个执行计划的绑定变量值组合在一起(以生成一个新的游标)。

SQL代码, 略.

总的来讲,为了提高执查询优化器生成高效的执行计划的可能性,最好不要使用绑定变量。绑定变量有时候可能有用。遗憾的是,生成的执行计划是否高效只能看运气如何。唯一的例外是,Oracle数据库11g中的新的扩展的游标共享会自动识别这个问题。

2.5.3 最佳实践

使用任何特性都需要权衡利弊得失。有些情况下,这是比较容易决定的。例如,在不涉及到Where从句(如普通的插入语句)的时候,就没理由不使用绑定变量。另一方面,在柱状图信息对查询优化器有很大影响的情况下,最好不要使用绑定变量。否则,可能会在进行绑定变量窥视的时候遇到较大负面风险。不过,还有以下两个关键案例可供参考:

  • SQL语句处理少量数据:每逢被处理的数据量很少的时候,解析时间有可能会接近甚至高于执行时间。在这种情况下,使用绑定变量就经常是一种较优选择。特别是在SQL语句将会频繁执行的情况下。数据资料系统(data entry system,常常也称之为OLTP系统)是典型的使用这种SQL语句的系统。
  • SQL语句处理大量数据:在大量数据被处理的情况下,解析时间常常比执行时间要少好几个数量级。在这种情况下,使用绑定变量对于总的响应时间(response time)几乎没有影响,但是它也会提高查询优化器生成低效的执行计划的风险。因此不要使用绑定变量。批量任务处理(batch job)、报表生成或者运用OLAP工具的数据仓库(data warehouse)环境是使用这种SQL的典型场景。

EOF

此文作者:, 位于 Database 分类 标签: on .
转载须以超链接形式标明文章原始出处和作者信息及版权声明.