Sql 我想优化这个查询

Sql 我想优化这个查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有以下表格: dbo.Details Name Type SubType SerialNumber D_01 TxA STxA1 4 D_02 TxB STxB2 3 D_03 TxC STxC1 2 D_04 TxD STxD1 7 D_05 TxD STxD1 1

我有以下表格:

dbo.Details
Name     Type  SubType  SerialNumber  
D_01     TxA    STxA1     4            
D_02     TxB    STxB2     3            
D_03     TxC    STxC1     2            
D_04     TxD    STxD1     7           
D_05     TxD    STxD1     1            
D_06     TxD    STxD1     9            

dbo.DetailsType
Code Name
TxA   A
TxB   B
TxC   C
...

dbo.DetailsSubType
Code    Type    Name  CustomOR
STxA1   TxA     A1      1
STxA2   TxA     A2      0
STxB1   TxB     B1      1
STxB2   TxB     B2      0
STxC1   TxC     C1      1
STxC2   TxC     C2      0
STxD    TxD     D1      1
我想知道您认为哪种查询(A或B)是最佳的,请解释:

查询A

CREATE PROCEDURE XXX
(
    @type nvarchar(10),
    @subType nvarchar(10) = null
)
AS
BEGIN 
declare @custom bit  = 0;
if (@subType is not null)
begin
    select @custom = CustomOR from dbo.DetailsSubType where SubType = @subType
end


select 
    DTST.SubType,
    DT.SerialNumber
from dbo.Details as  DT
left join DetailsSubType as DTST
    on DT.SubType = DTST.Code
where 
    DT.Type = @type
    and
    (
      @subType is null or
      (@custom = 0 and DTST.CustomOR= 0) or 
      (@custom = 1 and DT.SubType = @subType)
    )
END 
查询B

   declare @custom bit  = 0;
if (@subType is not null)
begin
    select @custom = CustomOR from dbo.DetailsSubType where SubType = @subType
end
if (@custom = 0)
begin
        select 
            DTST.SubType,
            DT.SerialNumber
        from dbo.Details as  DT
        left join DetailsSubType as DTST
            on DT.SubType = DTST.Code
        where 
            DT.Type = @type
            and
            DTST.CustomOR = 0
end
else
begin
        select 
            DTST.SubType,
            DT.SerialNumber
        from dbo.Details as  DT
        left join DetailsSubType as DTST
            on DT.SubType = DTST.Code
        where 
            DT.Type = @type
            and
            (DTST.CustomOR = 1 and DT.SubType = @subType)
end
不幸的是,两者都不是最优的。我猜您关心的是性能和查询的执行计划。第二种方法无疑为SQL Server提供了更好的优化计划机会——这仅仅是因为
很难优化

但这并没有考虑到“参数嗅探”。关于这个问题有很多文章(这是一篇合理的文章)

参数嗅探意味着SQL Server在第一次调用存储过程时编译查询。这节省了重新编译查询的开销——如果您有很多“小”查询,这一节省非常重要。但对于更大的查询来说,这是一个愚蠢的交易——因为它没有考虑表上的统计数据


我建议你研究一下有关这方面的文章。您可能会发现第二种解决方案就足够了。您可能会发现,只需添加
选项recompile
就足够了。您可能会发现,您希望将查询构造为动态SQL——嘿,您知道它无论如何都会被重新编译。但是你可以做出更明智的决定。

你可以考虑写三个查询来划分你的结果,其中每个查询都处理你的一个或谓词,并结合所有的结果。

在伪代码中:

SELECT ... FROM ... WHERE @subType is null
UNION ALL
SELECT ... FROM ... WHERE @subType is NOT null AND DTST.CustomOR = 0 AND @custom = 0
UNION ALL
SELECT ... FROM ... WHERE @subType is NOT null AND DT.SubType = @subType AND @custom = 1

话虽如此,我实际上认为您应该更改数据模型。这是非常有(和非常缓慢)推进与此设置。您可能没有正确规范化数据库。

这个问题更适合dbo。DetailsSubType没有子类型。你能解释一下你想达到什么目的吗?例如@subtype为null时,则DetailsSubType.customOR必须为=0