Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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
C# 使用替换和长度检查避免SQL不在_C#_.net_Sql_Sql Server_Tsql - Fatal编程技术网

C# 使用替换和长度检查避免SQL不在

C# 使用替换和长度检查避免SQL不在,c#,.net,sql,sql-server,tsql,C#,.net,Sql,Sql Server,Tsql,在这种情况下,我必须动态创建我的SQL字符串,并且我尝试在可能的情况下使用paramaters和sp_executesql,以便重用查询计划。在做了大量的在线阅读和个人体验后,我发现“不在”和“内部/左侧连接”在基本(最左侧)表很大(1.5M行,约50列)的情况下执行速度慢且成本高。我也读过,应该避免使用任何类型的函数,因为它会减慢查询速度,所以我想知道哪种更糟糕 我过去曾使用过这种解决方法,但我不确定这是否是最好的方法,以避免在传递包含3个字符串的列表时(例如,在元素之间)对项目列表使用“不在

在这种情况下,我必须动态创建我的SQL字符串,并且我尝试在可能的情况下使用paramaters和sp_executesql,以便重用查询计划。在做了大量的在线阅读和个人体验后,我发现“不在”和“内部/左侧连接”在基本(最左侧)表很大(1.5M行,约50列)的情况下执行速度慢且成本高。我也读过,应该避免使用任何类型的函数,因为它会减慢查询速度,所以我想知道哪种更糟糕

我过去曾使用过这种解决方法,但我不确定这是否是最好的方法,以避免在传递包含3个字符串的列表时(例如,在元素之间)对项目列表使用“不在”选项:

而不是:

[col] NOT IN('ABD', 'RDF', 'TRM', 'HYP', 'UOE') 
…假设字符串列表的长度为1到大约80个可能的值,并且此方法也不适合进行参数化

在本例中,我可以使用“=”表示不在,我将使用传统的列表技术表示在,或!=如果这是一个更快的方法,尽管我对此表示怀疑。这比使用NOT IN快吗

作为可能的第三种选择,如果我知道所有其他可能性(可能性,可能比列表长80-95倍)并通过这些可能性会怎么样;这将在应用程序的业务层中完成,以减轻SQL Server的工作负载。查询计划重用的可能性不是很高,但是如果它能让一个大的讨厌的查询缩短一两秒,为什么不呢

我还擅长SQL CLR函数的创建。既然上面是字符串操作,那么CLR函数会是最好的吗

想法

提前感谢您的帮助/建议等

我发现,当基表(最左侧)很大时,“notin”和“INNER/LEFT JOIN”的执行速度很慢,成本也很高

如果正确地为表编制索引,速度应该不会太慢。如果您有一个依赖子查询,则可能会使查询速度变慢。也就是说,必须为表中的每一行重新计算查询,因为子查询引用外部查询中的值

我还读到,应该避免使用任何类型的函数,因为它会减慢查询速度

视情况而定<代码>从…中选择函数(x)可能不会对性能产生很大影响。问题在于在查询的其他位置使用列的函数时,例如连接条件、WHERE子句或ORDER BY,因为这可能意味着无法使用索引。但是,一个定值函数不是问题


关于您的查询,我会先尝试使用
[col]NOT IN('ABD','RDF','TRM','HYP','UOE')
。如果这很慢,请确保您已对该表进行了适当的索引。

首先,由于您只筛选出了一小部分记录,因此可能根本没有使用
列上的索引,因此SARG功能是没有意义的

这样就剩下了查询计划重用

  • 如果您使用的是SQL Server 2008,请将
    @param1
    替换为表值参数,并让应用程序传递该参数,而不是分隔列表。这完全解决了你的问题

  • 如果您使用的是SQLServer2005,我认为这无关紧要。您可以拆分带分隔符的列表并对表使用
    不在
    /
    不存在
    ,但是如果在
    上得不到索引查找又有什么意义呢

有人能讲到最后一点吗?将列表拆分为一个表变量,然后反连接它是否可以节省足够的CPU周期来抵消设置成本

编辑,SQL Server 2005使用XML的第三种方法,灵感来自OMG Ponies的链接:

DECLARE @not_in_xml XML
SET @not_in_xml = N'<values><value>ABD</value><value>RDF</value></values>'

SELECT * FROM Table1 
WHERE @not_in_xml.exist('/values/value[text()=sql:column("col")]') = 0
在xml中声明@not_
设置@not_in_xml=N'ABDRDF'
从表1中选择*
其中@not_在_xml.exist('/values/value[text()=sql:column(“col”)]')=0
我不知道与分隔列表或TVP相比,它的性能有多好。

正如Donald Knuth经常(错误)引用的那样,“过早优化是万恶之源”。
因此,首先,您确定如果您以最清晰、最简单的方式(既写又读)编写代码,它的执行速度会很慢吗?如果没有,请在开始使用任何“聪明”的优化技巧之前检查它

如果代码很慢,请仔细检查查询计划。大多数情况下,查询执行比查询编译花费的时间要长得多,因此通常您不必担心查询计划的重用。因此,构建最佳索引和/或表结构通常比调整查询的构建方式提供更好的结果

例如,我严重怀疑使用LEN和REPLACE的查询是否比不使用LEN和REPLACE的查询具有更好的性能—在这两种情况下,所有行都将被扫描并检查是否匹配。对于足够长的列表,MSSQL优化器将自动创建临时表以优化相等比较。
更重要的是,像这样的技巧往往会引入bug:比如说,如果[col]='AB',您的示例将无法正常工作

IN查询通常比NOT IN查询快,因为对于IN查询,只有一部分行足以进行检查。该方法的效率取决于您是否能够足够快地为输入获取正确的列表

说到将可变长度列表传递给服务器,这里有很多关于SO和其他地方的讨论。一般来说,您的选择是:

  • 表值参数(仅限MSSQL 2008+版)
  • 动态构造的SQL(容易出错和/或不安全)
  • 临时表(适用于长列表,短列表的写入和执行时间开销可能太大)
  • 分隔字符串(适用于“行为良好”值的短列表,如少数整数)
  • XML参数(有点复杂,但工作良好-如果您使用一个好的XML库,并且不“手工”构造复杂的XML文本)
下面是一篇关于这些技术以及其他一些技术的综述。

W
DECLARE @not_in_xml XML
SET @not_in_xml = N'<values><value>ABD</value><value>RDF</value></values>'

SELECT * FROM Table1 
WHERE @not_in_xml.exist('/values/value[text()=sql:column("col")]') = 0