Oracle参数化查询性能

问题描述 投票:1回答:1

以下查询之间的执行时间差异太大。这些是使用Entity Framework从应用程序生成的查询。

第一个是非参数化查询,需要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;

我知道参数化查询对于缓存非常有用。如何找到提高参数化查询性能的方法?

oracle performance query-optimization sql-tuning
1个回答
3
投票

“参数化查询对于缓存非常有用”

需要明确的是,当我们使用绑定变量时,缓存的是解析的查询和执行计划。假设是给出像...这样的查询

where col1 = :p1
and   col2 = :p2

......当:p1 = 23 and :p2 = 42:p1 = 42 and :p2 = 23一样时,同样的计划也有效。如果我们的数据具有均匀分布,则假设保持良好。但是,如果我们的数据存在某种形式的偏差,我们最终可能会得到一个适用于某个特定值组合的计划,但对于我们的用户需要运行的大多数其他查询而言,这是一个垃圾。这是一种被称为bind variable peeking的现象。

日期范围查询是一个臭名昭着的例子。您的第一个查询提供的值将与明确定义的范围的记录匹配。假设检索表的一小部分。但是,对于第二个查询,指定的日期范围可以是任何东西:一天,一周,一个月,一年,一个 - 你得到的图片。

结果是,索引范围扫描对于第一个查询可能非常有效,而对于第二个查询则是非常有效。

要了解更多信息,您需要探索特定查询:

  • 运行两个版本的查询的解释计划,了解差异。 (确保您正在使用逼真的(类似生产的)数据:不仅仅是数量,还包括分布和偏差。
  • 检查统计信息是否准确,并考虑刷新它们是否有帮助。
  • 理解数据的偏差,并检查您是否遇到绑定变量偷看。也许你需要看看adaptive cursors
  • 或者,您可能需要避免使用绑定变量。特别是对于大型表的日期范围查询,传递日期参数的实际值并不罕见。每次执行时解析查询的成本都会通过为每组参数获取最佳计划来抵消。

简而言之,我们应该了解我们的数据以及用户使用它的方式,然后相应地编写查询。

© www.soinside.com 2019 - 2024. All rights reserved.