以下查询之间的执行时间差异太大。这些是使用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;
我知道参数化查询对于缓存非常有用。如何找到提高参数化查询性能的方法?
“参数化查询对于缓存非常有用”
需要明确的是,当我们使用绑定变量时,缓存的是解析的查询和执行计划。假设是给出像...这样的查询
where col1 = :p1
and col2 = :p2
......当:p1 = 23 and :p2 = 42
和:p1 = 42 and :p2 = 23
一样时,同样的计划也有效。如果我们的数据具有均匀分布,则假设保持良好。但是,如果我们的数据存在某种形式的偏差,我们最终可能会得到一个适用于某个特定值组合的计划,但对于我们的用户需要运行的大多数其他查询而言,这是一个垃圾。这是一种被称为bind variable peeking的现象。
日期范围查询是一个臭名昭着的例子。您的第一个查询提供的值将与明确定义的范围的记录匹配。假设检索表的一小部分。但是,对于第二个查询,指定的日期范围可以是任何东西:一天,一周,一个月,一年,一个 - 你得到的图片。
结果是,索引范围扫描对于第一个查询可能非常有效,而对于第二个查询则是非常有效。
要了解更多信息,您需要探索特定查询:
简而言之,我们应该了解我们的数据以及用户使用它的方式,然后相应地编写查询。