Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server存储过程性能影响_Sql_Sql Server_Stored Procedures - Fatal编程技术网

SQL Server存储过程性能影响

SQL Server存储过程性能影响,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我想写一个多用途的存储过程。有谁能帮我找到用这些方法在SQLServer中编写存储过程的最佳实践吗?它们对性能的影响是什么 方法1: 参数@KEY,@VALUE IF @KEY = 'ISACTIVE' BEGIN SELECT ID, STATECODE, STATENAME, ISACTIVE FROM STATE WHERE ISACTIVE = @VALUE END ELSE IF @KEY = 'STATECODE' BEGIN SELECT ID

我想写一个多用途的存储过程。有谁能帮我找到用这些方法在SQLServer中编写存储过程的最佳实践吗?它们对性能的影响是什么

方法1: 参数@KEY,@VALUE

IF @KEY = 'ISACTIVE'
BEGIN 
    SELECT ID, STATECODE, STATENAME, ISACTIVE 
    FROM STATE 
    WHERE ISACTIVE = @VALUE
END
ELSE IF @KEY = 'STATECODE'
BEGIN
    SELECT ID, STATECODE, STATENAME, ISACTIVE 
    FROM STATE  
    WHERE STATECODE = @VALUE
END
ELSE
BEGIN
    SELECT ID, STATECODE, STATENAME, ISACTIVE 
    FROM STATE
END
DECLARE @SQLQRY NVARCHAR(500)
SET @SQLQRY = 'SELECT ID, STATECODE, STATENAME, ISACTIVE FROM STATE WHERE ' + @KEY +' = ' + @VALUE
EXEC @SQLQRY
方法:2 参数@ISACTIVE、@STATECODE

SELECT ID, STATECODE, STATENAME, ISACTIVE 
FROM STATE
WHERE ISACTIVE = ISNULL(@ISACTIVE, ISACTIVE) 
  AND STATECODE = ISNULL(@STATECODE,STATECODE)
方法:3

参数@KEY,@VALUE

IF @KEY = 'ISACTIVE'
BEGIN 
    SELECT ID, STATECODE, STATENAME, ISACTIVE 
    FROM STATE 
    WHERE ISACTIVE = @VALUE
END
ELSE IF @KEY = 'STATECODE'
BEGIN
    SELECT ID, STATECODE, STATENAME, ISACTIVE 
    FROM STATE  
    WHERE STATECODE = @VALUE
END
ELSE
BEGIN
    SELECT ID, STATECODE, STATENAME, ISACTIVE 
    FROM STATE
END
DECLARE @SQLQRY NVARCHAR(500)
SET @SQLQRY = 'SELECT ID, STATECODE, STATENAME, ISACTIVE FROM STATE WHERE ' + @KEY +' = ' + @VALUE
EXEC @SQLQRY
在性能和可重用性方面,哪种方法是最好的


或者有其他的选择来实现这一点吗?

我肯定会选择方法2,这在我看来是既可维护又永久的

在方法1中,您复制了代码,因此在维护方面,这不是最好的方法

在方法3中,使用动态sql查询并不是最好的方法,因为它既不提供intellisense支持,也限制了sql server优化性能的能力

如果您遇到任何性能问题,请考虑在“ISActudio”和“StaseCeCd”列上引入索引。还要分析查询执行计划,并在需要时使用探查器进行进一步调查

我想写一个多用途的存储过程

考虑到这一愿望(尽管我对这一需求有顾虑),这取决于

  • 方法1:随着业务规则变得复杂,您将开始重复大量代码。当您意识到,您有多个重复的选择,可能有多个联接或
    EXISTS
    子句,可能另一个程序员不得不修改某些内容,却忘记编辑其中一个查询。当您开始同时应用多个过滤器时,事情变得更加复杂(如
    SELECT
    where
    IsActive=0和StateCode='AR'
    )。这种方法使得根据要筛选的键返回不同的结果集变得更容易
  • Aproach 2:您可以将过滤器堆叠在一起,只需编写
    选择
    一次,但如果您有许多行,并且过滤器应用于不同的表,则会降低性能。另一个问题是,您可能必须为比较的两端提供替换值:如果我们只想选择
    StateCode
    上有
    NULL
    的记录,那么您必须执行类似
    ISNULL(StateCode,'SomeImpossibleStateCode')=ISNULL(@StateCode,'SomeImpossibleStateCode')的筛选
    或类似的
    (@StateCode为NULL,StateCode为NULL)或(@StateCode=StateCode)
  • 方法3:由于它是动态的,维护起来比较困难,依赖表/列不会出现在
    sysdepends
    之类的视图上,您可能需要采取额外的措施来防止SQL注入。但是,它提供了完全避免条件过滤器的灵活性,这将使查询更简单、性能更高。您甚至可以接收一个表作为输入参数,其中包括要应用的筛选器、链接它们的逻辑运算符(
    )以及筛选器前置项
结论:

  • 如果您的表不大,并且您可能搜索的键数量较少,方法2将是最好的方法,尽管您必须测试性能

  • 方法3似乎最适合处理所有场景,包括性能

  • 我肯定会避免方法1,因为它很容易出现维护错误。如果您觉得不同的键需要返回不同的列或应用不同的查询条件,那么是时候将do-it all SP拆分为不同的SP了

必须阅读:由Erland Sommarskog编写。按现状,方法2不好,但可以成为最好的方法

以下是链接文章的简短摘要

从性能角度来看,方法1是好的。Optimizer可以生成良好的计划并使用可用的索引。 这里的问题是查询的可能变体/排列的数量。如果有三个参数Key1、Key2、Key3,那么如果有三层深度,它将变成一个相当难看的嵌套。如果再添加几个参数,从维护的角度来看,这将变得不切实际

方法2从维护的角度来看是好的,但从性能的角度来看,“按现状”是坏的
ISACTIVE=ISNULL(@ISACTIVE,ISACTIVE)
即使在
@ISACTIVE
为NULL时也会被计算,这可能会妨碍索引的有效使用

应按照以下方式重写查询:

SELECT ID, STATECODE, STATENAME, ISACTIVE 
FROM STATE
WHERE
    (ISACTIVE = @ISACTIVE OR @ISACTIVE IS NULL) 
    AND (STATECODE = @STATECODE OR @STATECODE IS NULL)
OPTION(RECOMPILE);
选项(重新编译)
非常重要。本质上,它允许Optimizer将参数的实际值内联到查询中,简化逻辑表达式并生成计划,这与方法1一样好或更好。有关详细信息,请参阅本文


方法3将产生良好的计划,如方法1,但不是方法2的最佳计划。虽然动态SQL有其困难,但维护也不错。如果你走这条路,你应该阅读Erland的另一篇文章。

你应该进行基准测试……但如果这是你的瓶颈,你会遇到更大的问题……这个表的大小是多少?这是来自内存,但我认为如果表大小小于64 KB,索引将不会产生任何影响,因为这是SQL Server读取的最小数据集。也就是说,绝对不建议使用方法3,因为它容易出现sql注入。就可重用性而言,第三种方法“可以”,但就性能而言,我建议使用方法1,因为SP是编译的,所以sql Server可以在编译时根据您的条件决定执行计划。在第三种方法中,也有可能在第三种应用程序中出现运行时错误