Oracle参数化查询性能

时间:2018-03-02 07:13:54

标签: oracle performance query-optimization sql-tuning

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

第一个是非参数化查询,需要 0,559 秒。

<div id="statistiktext"></div>

function showsomething(){
    for($i = 0; $i < count($statistik); $i++){
        echo $something[$i]['number'] . "<br>";
    }
}
?>

<div id="statistiktextdiv" style="visibility: hidden;"><?php showsomething(); ?></div>

另一个参数化了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" >= 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;

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

1 个答案:

答案 0 :(得分:3)

  

&#34;参数化查询对于缓存非常有用&#34;

为了清楚起见,当我们使用绑定变量时,缓存的是解析的查询和执行计划。假设是给出了像...这样的查询。

where col1 = :p1
and   col2 = :p2

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

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

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

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

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

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