我们进行了重构并用参数化请求替换了2个类似的请求
a.isGood =:1
在使用此参数并将参数' Y'通常被执行的时间更长(与参数' N'几乎相同)。我们使用alter system flush shared_pool命令并请求参数' Y'已完成快速(如重构前),同时请求参数' N'挂了很久。
您可以通过参数' N'来了解数据库中的行数。更多的是' Y'
Oracle 10g
为什么会这样?
答案 0 :(得分:2)
我假设您在该列上有索引,否则无论Y / N组合如何,性能都是相同的。由于Oracle的优化器 Bind Peeking 与直方图组合在一起,数据分布偏差的列,我已经看到10g +上发生了这种情况。当使用参数method_opt并使用' FOR ALL COLUMNS SIZE AUTO'收集表统计数据时,会自动创建直方图。 (以及其他价值观)。 Oracle优化了对该查询的第一次执行中提供的绑定变量中的值的查询。如果您第一次使用Y运行查询,Oracle可能希望使用索引而不是全表扫描,因为Y将返回少量行。下次使用N运行查询时,Oracle将重复第一个执行计划,这对N来说是一个糟糕的选择,因为它将返回绝大多数行。
执行计划缓存在SGA中。一旦刷新它,您将在第一次再次运行查询时获得全新的执行计划。
我的建议是:
答案 1 :(得分:1)
如果列isGood
具有99,000个“N”值和1,000个“Y”值,并且您使用条件isGood = 'Y'
运行,那么使用索引查找结果可能是合适的:您是返回1%的行。如果使用条件isGood = 'N'
运行查询,则完整的表扫描会更合适,因为无论如何您都要返回大部分表。如果您要使用N
条件的索引,那么您将为每个数据项查找执行额外的索引查找。
虽然一般规则是绑定参数是好的,但如果查询需要两个不同的计划,则在这种情况下可能会出现问题。使用绑定参数场景:
SELECT * FROM x WHERE isGood = :1
将解析语句并计算并保存在sql缓存中的计划。同一计划将用于两种不可取的查询场景。但是:
SELECT * FROM x WHERE isGood = 'Y'
SELECT * FROM x WHERE isGood = 'N'
将导致两个计划存储在sql缓存中,希望每个计划都有适当的查询计划。版本11g避免了adaptive cursor sharing的这个问题,它可以对不同的绑定变量值使用不同的计划。
您需要查看您的计划(EXPLAIN PLAN
)以了解您的案例中发生的情况。刷新缓存,尝试一种方法,检查计划;尝试另一个,检查计划。它可能会让您了解您的案例中发生了什么。您可能会跟进其他一些可能有所帮助的主题,例如: