我正在使用 SqlParameter 将值传递给我的查询
假设我的DOS numeric(3,0)
表中有一个字段。
我的查询类似于SELECT * FROM ENT WHERE ENT.DOS = @DOS
.
问题是我在运行时不知道 ENT.DOS 字段的类型(我的引擎很复杂......),所以我在创建 SqlParameter 时没有指定任何精度或比例。
例如,如果我想要 DOS = 1,Precision 将设置为 1,Scale 设置为 0。
它有效,这不是重点。问题是:它很慢。
如果我指定真正的 Precision 和 Scale 值,查询会运行得很快。
我可以在 Management Studio 中重现该问题:
在数据库中: DOS = numeric(3,0) TICOD = char(1) PICOD = numeric(8,0) PINO = numeric(8,0) ENT_ID = int
慢版:
DECLARE @DOS as numeric(1,0) = 1
DECLARE @TICOD as varchar(1) = 'C'
DECLARE @PICOD as numeric(1,0) = 3
DECLARE @PINO as numeric(8,0) = 99999999
DECLARE @ENT_ID as numeric(8,0) = 99999999
SELECT TOP 1 *
FROM ENT AS ENT WITH(NOLOCK)
WHERE
(CE4 = '1') and (
( DOS = @DOS and TICOD = @TICOD and PICOD = @PICOD and PINO < @PINO ) or
( DOS = @DOS and TICOD = @TICOD and PICOD < @PICOD ) or
( DOS = @DOS and TICOD < @TICOD ) or
( DOS< @DOS )
)
order by DOS desc,TICOD desc,PICOD desc,PINO desc,ENT_ID desc
OPTION (FAST 1)
快速版本(具有正确的参数类型):
declare @DOS as numeric(3,0) = 1
declare @TICOD as char(1) = 'C'
declare @PICOD as numeric(5,0) = 3
declare @PINO as numeric(8,0) = 99999999
declare @ENT_ID as int = 99999999
SELECT TOP 1 *
FROM ENT AS ENT WITH(NOLOCK)
WHERE
(CE4 = '1') and (
(DOS = @DOS and TICOD = @TICOD and PICOD = @PICOD and PINO = @PINO and ENT_ID < @ENT_ID ) or
( DOS = @DOS and TICOD = @TICOD and PICOD = @PICOD and PINO < @PINO ) or
( DOS = @DOS and TICOD = @TICOD and PICOD < @PICOD ) or
( DOS = @DOS and TICOD < @TICOD ) or
( DOS< @DOS )
)
order by DOS desc,TICOD desc,PICOD desc,PINO desc,ENT_ID desc
OPTION (FAST 1)
所以我的问题是:有没有一种方法可以为十进制类型声明 SqlParameter 而无需指定 Precision 和 Scale 并且查询运行速度很快?
更新 1:
执行计划:
正确的数据类型: https ://dl.dropboxusercontent.com/u/14168890/SqlParameter/exec_plan_fast.sqlplan
该计划显示搜索谓词
1 Seek Keys1: End: DOS < @DOS,
2 Seek Keys1: Prefix: DOS = @DOS, End: TICOD < @TICOD,
3 Seek Keys1: Prefix: DOS, TICOD = @DOS, @TICOD, End: PICOD < @PICOD,
4 Seek Keys1: Prefix: DOS, TICOD, PICOD = @DOS, @TICOD, @PICOD, End: PINO < @PINO,
5 Seek Keys1: Prefix: DOS, TICOD, PICOD, PINO = @DOS, @TICOD, @PICOD, @PINO, End: ENT_ID < @ENT_ID
不匹配的数据类型: https ://dl.dropboxusercontent.com/u/14168890/SqlParameter/exec_plan_slow.sqlplan
该计划显示了谓词进入过滤器的扫描。
不匹配的数据类型(FORCESEEK)
: https ://dl.dropboxusercontent.com/u/14168890/SqlParameter/exec_plan_forceseek.sqlplan
索引 GTFENT_G 是:DOS,TICOD,PICOD,PINO,ENT_ID
另外,我还测试了在整数类型中声明实际上是整数的数值,慢的变快。