Oracle 参数化查询性能
Posted
技术标签:
【中文标题】Oracle 参数化查询性能【英文标题】:Oracle Parameterized Query Performance 【发布时间】:2018-03-02 07:13:53 【问题描述】:以下查询的执行时间差异太大。这些是使用实体框架的应用程序生成的查询。
第一个是非参数化查询,耗时 0,559 秒。
SELECT
"Project1"."C2" AS "C1",
"Project1"."C1" AS "C2",
"Project1"."KEYFIELD" AS "KEYFIELD"
FROM ( SELECT
"Extent1"."KEYFIELD" AS "KEYFIELD",
CAST( "Extent1"."LOCALDT" AS date) AS "C1",
2 AS "C2"
FROM "MYTABLE" "Extent1"
WHERE (
("Extent1"."LOCALDT" >= to_timestamp('2017-01-01','YYYY-MM-DD')) AND
("Extent1"."LOCALDT" <= to_timestamp('2018-01-01','YYYY-MM-DD'))
)
) "Project1"
ORDER BY "Project1"."C1" DESC;
另一个有参数化的 WHERE 子句。获取数据需要 18,372 秒:
SELECT
"Project1"."C2" AS "C1",
"Project1"."C1" AS "C2",
"Project1"."KEYFIELD" AS "KEYFIELD"
FROM ( SELECT
"Extent1"."KEYFIELD" AS "KEYFIELD",
CAST( "Extent1"."LOCALDT" AS date) AS "C1",
2 AS "C2"
FROM "MYTABLE" "Extent1"
WHERE (
("Extent1"."LOCALDT" >= :p__linq__0) AND
("Extent1"."LOCALDT" <= :p__linq__1)
)
) "Project1"
ORDER BY "Project1"."C1" DESC;
我知道参数化查询对于缓存非常有用。如何找到提高参数化查询性能的方法?
【问题讨论】:
【参考方案1】:“参数化查询对于缓存非常有用”
需要明确的是,当我们使用绑定变量时,缓存的是解析后的查询和执行计划。假设是给定这样的查询 ...
where col1 = :p1
and col2 = :p2
...:p1 = 23 and :p2 = 42
和:p1 = 42 and :p2 = 23
时相同的计划也适用。如果我们的数据分布均匀,则假设成立。但是,如果我们的数据存在某种形式的偏差,我们最终可能会制定一个计划,该计划适用于一种特定的值组合,但对于我们用户需要运行的大多数其他查询来说却是垃圾。这种现象称为bind variable peeking。
日期范围查询是一个臭名昭著的例子。您的第一个查询提供的值将与定义明确的范围内的记录相匹配。假设检索表的一个窄片。但是,对于第二个查询,指定的日期范围可以是任何时间:一天、一周、一个月、一年,a - 你明白了。
结果是,索引范围扫描对于第一个查询可能非常有效,而对于第二个查询则令人震惊。
要了解更多,您需要探索特定查询:
为两个版本的查询运行解释计划,了解差异。 (确保您使用的是真实的(类似生产的)数据:不仅是数量,还有分布和偏差。 检查统计信息是否准确,并考虑刷新它们是否有帮助。 了解数据的偏差,并检查您是否遭受绑定变量窥视。或许你需要看看adaptive cursors。 或者,您可能需要避免使用绑定变量。特别是对于大型表的日期范围查询,传递日期参数的实际值并不罕见。通过为每组参数获取最佳计划来抵消每次执行查询时解析查询的成本。简而言之,我们应该了解我们的数据以及用户需要使用它的方式,然后相应地编写查询。
【讨论】:
感谢您指出未记录的提示BIND_AWARE
!
@WernfriedDomscheit - 不要想我,谢谢 Tim Hall。他是个好孩子:)以上是关于Oracle 参数化查询性能的主要内容,如果未能解决你的问题,请参考以下文章