一个常见的经典问题,也是一个难缠的业界难题,基于Oracle的程序时快时慢,很多资深的DBA面临这个问题也是束手无策,没有一个最优的解决方案。如果你的数据库正经历各种性能问题,不妨联系中亦科技试一试,看我们如何解决你的数据库忧虑。
----中亦科技老猫(陈宏义)
问题来了
一个新的基金客户,初次碰面,估计会有一些技术难题的考验,我一到场,开发团队的领导直奔主题,我这里有个问题,前面那家厂商提供了一个解决方案,我们很难接受,不知你有什么更好的办法。
注:下边的代码是经过处理后的数据。
问题语句:
出现问题的执行计划,这个图最好放大了仔细看看
如果status字段上数据分布存在严重的数据倾斜,举个例子,一个学校,男女比例严重失调,男生有99990人,女生有10人,如果数据按照性别这个字段分布的化,数据就是倾斜的,如果这时过滤条件是性别字段,SQL就会时快时慢。这正是客户目前正面临的问题。
倾斜就“歪”呗
简单说,使用绑定变量情况下,如果关键条件上数据分布严重倾斜,生成执行计划时,绑定变量窥视到一个数据量非常小的值,cardinality为1,此时执行速度一般会很快,当用这个执行计划执行到拥有300万行数据的值的时候,性能就严重下降。这就是“歪”。之所以“歪”是因为使用绑定变量的话,避免了重复解析,只有第一次生成执行计划时的代入值是能偷窥到的,也就是说只有一个执行计划。而这个案例里,数据分布不均,STATUS='INVALID'时走索引合适,STATUS=‘VALID’时走全表合适。这时总有一个执行计划是不好的,这就是经典的时快时慢的性能难题。
这里解释下cardinality,如果按照前面的例子:一个学校,男女比例严重失调,男生有99990人,女生有10人,那么,查看所有女生的cardinality为:100000*(10/100000),所有男生的
cardinality为100000*(99990/10000)
第三步过滤条件为"T1"."STATUS"=:B1的E-ROWS(评估行数)和A-ROWS(实际行数)相差非常大,直接导致CBO选择使用nested loop进行连接。那为什么会出现这种现象呢?原因很简单,生成执行计划的绑定变量B1的值是'INVALID',这个列上的数据分布倾斜非常严重。STATUS的值为'INVALID'只有16行,而值为VALID的数据占了绝大多数1132K。所以,我们一般建议开发人员在这样的条件上,不要使用绑定变量。
很多资深DBA遇到这类问题也都有自己的处理方法,但究竟有没有一种最优的方案?大家思考一下碰到这种问题,你怎么办?
自己思考一下,下面是思考时间.....
....
....
...
...
..
..
.
.
解决方案
到目前为止一切很顺利,问题变成了常规问题,常规解决方案:
1. 由于NDV(
Number of distinct values
)很小,所以,可以不绑定变量,直接使用字面值,批量程序,可以忽略解析的消耗。
2. 删除直方图,让CBO认为数据是均匀分布的,这个可能牺牲掉小数据量时的性能优势。
3. SQL Profile绑定执行计划。这个作法和第二种方案差不多。换了一种实现方式。
4. ACS(Adaptive Cursor Sharing),这个特性一般我们不建议启用,如果为了这个问题打开,不能说是一个好方案。暂时不推荐。
这个时候我的内心是高兴不起来的,如果是这种常规问题, 由上一个数据库服务公司的DBA不至于不懂,谨慎的问了客户一句,『您的代码是用什么语言写的?procedure还是java之类的程序语言?』
客户答:"procedure"。
菊花保卫战
听到客户的回答,我菊花一紧,第一个解决方案不行了,PL/SQL中使用动态SQL,是件所有开发人员都无法接受的方法,我是作开出身的,是我我也不接受。
客户眼睛瞪得象豆包,来了一句『对呀,我们就是不想接受这个方案。以前这么写过,出过很多问题。』
心中窃喜,还好没直接推荐这种方案,菊花暂时保住了。
『那您能接受小数据量时,比现在慢一点,但是大数据量时会变成很快吗?』
『那您能接受小数据量时,比现在慢一点,但是大数据量时会变成很快吗?』
客户答:『最好不要这样,有更好的方案吗?我也懂一些SQL优化的原理,我们有时会绑定根本不存在的值。』
菊花忧矣。
有时候,有点压力的时候会有灵光乍现,此时我脑子里蹦出了第五种方案:
SQL Plan Baseline
之所以这个时候才蹦出了也是有原因的,讲真不是万不得已,使用SQL PLan Baseline我的内心也是抗拒的,我真的不太喜欢用sql plan baseline这个东西,它好象天生就是为EM设计的,用起来麻烦,不过为了客户内裤也得用呀...
SQL Plan Baseline配置
捕获计划:
accept:
SQL_PLAN_gd8s9vjf5z9t89e2752cc这个plan,这样我们就接爱了两个plan了,就是说在每次SQL执行时,CBO会recost一下,决定用哪一个plan来执行当前的SQL。
测试验证
测试语句:
执行计划:
再绑定B1:='VALID';
执行计划:
老猫说:
在GCS时每天都有大量复杂的,涉及到bug的问题处理,仿佛人生的主题就只是处理难题。来中亦安图以后,这个团队的风气和GCS如出一辙,喜欢去跟一些难点问题死磕。这是我们这个DBA团队的最优良的传统。如果你的系统有问题,可以让我们尝试“死磕”一下。
总结
这是个很简单案例,我想说的是,我们作DBA的总是要结合现场情况,在把问题分析最细粒度的情况下,利用Oracle强大的功能,为客户提供最便利的、最省成本的解决方案。
我们不创造技术,我们只是技术的搬运工。
如果你的数据库还在面临这一类让你头疼的问题,不妨让我们尝试可以关注我们的公众号,联系我们试一试。
本文转载于中亦安图