【问题标题】:Optimzing TSQL code [closed]优化 SQL 代码 [关闭]
【发布时间】:2010-06-16 14:25:34
【问题描述】:

我的工作是维护一个大量使用 SQL server (MSSQL2005) 的应用程序。
到目前为止,中间服务器将 TSQL 代码存储在 XML 中,并在不使用存储过程的情况下发送动态 TSQL 查询。
因为我能够更改那些 XML 查询,所以我想将我的大部分查询迁移到存储过程。
问题如下:

我的大多数查询对一张表都有相同的 Where 条件

示例:

Select 
   .....
from ....
where ....
and (a.vrsta_id = @vrsta_id  or @vrsta_id = 0)
and (a.podvrsta_id = @podvrsta_id or @podvrsta_id = 0)
and (a.podgrupa_2 = @podgrupa2_id or @podgrupa2_id = 0)
and (
 (a.id in (select art_id from osobina_veze where podosobina_id in (select ado from dbo.fn_ado_param_int(@podosobina))
        group by art_id
        having count(art_id)= @podosobina_count ))
     or ('0' = @podosobina)
 )

它们在其他表上也有相同的 where 条件。

我应该如何组织我的代码?
什么是正确的方法?
我是不是该 制作我将在所有查询中使用的表值函数
或者每次执行proc时使用#Temp表和简单的内部连接我的查询? 还是使用由表值函数归档的#temp?
或者将所有查询都保留在这个大的 where 子句中,并希望索引能够完成它们的工作。
或使用 WITH(语句)

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql sqlperformance


    【解决方案1】:

    我开始意识到在单个查询中进行如此复杂的搜索并不是一个好主意。

    我更喜欢根据输入条件值构建 sql。 这使得 rsql server 更容易为每次搜索构建更好的执行计划。 这样我敢打赌,您的查询有一个次优的执行计划。

    我意识到这将包括动态 sql,因此适用于它的通常警告。

    【讨论】:

      【解决方案2】:

      您在这里有两个不同的功能关注点:从一个表中选择值以及选择要返回的列或要连接到该数据的其他表。如果您的一张桌子上过滤的项目数量可能很大,我倾向于将所选值的 PK 存储到中间或工作表中。如果它是一个永久表,您可以通过 SessionId 之类的东西来分隔不同的搜索,或者您可以通过从过滤例程传递到选择例程的随机值来分隔每组搜索结果。

      没有理由不能在动态 SQL 中保留过滤例程。但是,我不会尝试在 T-SQL 中执行动态 SQL。 T-SQL 对于字符串操作来说很糟糕。从中间层动态构建查询使您能够从 Where 子句中排除实际上未传递的元素。例如,不用and (a.vrsta_id = @vrsta_id or @vrsta_id = 0),您可以在@vrsta_id 实际上为零时完全排除这一行,或者在@vrsta_id 不为零时使用a.vrsta_id = @vrsta_id。通常,这种类型的查询会比一系列 OR 执行得更好。

      一旦您有了工作表,您的选择查询将如下所示:

      Select..
      From WorkTable As W
          Join ...
      
      Where SetId = 12345
          And ( OtherTable.Col = ....
      

      在这种情况下,SetId 将表示从过滤例程创建的项目集。

      【讨论】:

        【解决方案3】:

        您可以创建一个表值函数,该函数接受参数并返回匹配 a.id 值的表。然后,您可以将该函数内部连接到每个存储过程中的查询中。例如:

        create function dbo.GetMatches
        (
        @vrsta_id int,
        @podvrsta_id int,
        @podgrupa2_id int,
        @podosobina_count int
        )
        returns table
        as
        return
        Select 
        a.id
        from a
        where
        (a.vrsta_id = @vrsta_id  or @vrsta_id = 0)
        and (a.podvrsta_id = @podvrsta_id or @podvrsta_id = 0)
        and (a.podgrupa_2 = @podgrupa2_id or @podgrupa2_id = 0)
        and (
        (a.id in (select art_id from osobina_veze where podosobina_id in (select ado from dbo.fn_ado_param_int(@podosobina))
        group by art_id
        having count(art_id)= @podosobina_count ))
        or ('0' = @podosobina)
        )
        

        那么在这个例子中查询...

        select
        *
        from
        a
        inner join dbo.GetMatches(1,2,3,4) matches
        on a.id = matches.id
        inner join b on a.bID = b.bID -- example other table
        

        您也可以像这样在 where 语句中使用该函数...

        where
            a.id in (select id from dbo.GetMatches(1,2,3,4))
        

        【讨论】:

          猜你喜欢
          • 2016-11-04
          • 1970-01-01
          • 2011-11-02
          • 2011-11-03
          • 2017-02-18
          • 1970-01-01
          • 1970-01-01
          • 2011-11-24
          • 1970-01-01
          相关资源
          最近更新 更多