SQL Server查询的最大大小? IN子句?有更好的方法吗?

时间:2009-12-08 20:52:11

标签: sql sql-server tsql limits

  

可能重复:
  T-SQL WHERE col IN (…)

SQL Server查询的最大大小是多少? (字符数)

IN子句的最大大小?我想我看到有关于Oracle有1000项限制的东西,但你可以用ANDing 2 INs来解决这个问题。 SQL Server中的类似问题?

更新 那么,如果我需要从另一个系统(非关系数据库)中获取1000个GUID并对SQL Server执行“JOIN in code”,那么最好的方法是什么?是否要向IN子句提交1000个GUID列表? 或者是否有其他技术可以更有效地工作?

我没有对此进行过测试,但我想知道是否可以将GUID作为XML文档提交。例如

<guids>
    <guid>809674df-1c22-46eb-bf9a-33dc78beb44a</guid>
    <guid>257f537f-9c6b-4f14-a90c-ee613b4287f3</guid>
</guids>

然后针对Doc和Table执行某种XQuery JOIN。效率低于1000项IN条款?

4 个答案:

答案 0 :(得分:72)

每个SQL批处理必须符合Batch Size Limit:65,536 *网络数据包大小。

除此之外,您的查询受运行时条件的限制。它通常会耗尽堆栈大小,因为x IN(a,b,c)只是x = a OR x = b OR x = c,它创建一个类似于x = a OR的表达式树(x = b OR(x) = c)),因此大量的OR变得非常深。 SQL 7会命中SO at about 10k values in the IN,但是现在的堆栈更深(因为x64),所以它可以非常深。

<强>更新

您已经找到了Erland关于将列表/数组传递给SQL Server主题的文章。使用SQL 2008,您还可以Table Valued Parameters,它允许您将整个DataTable作为单个表类型参数传递并加入其中。

XML和XPath是另一种可行的解决方案:

SELECT ...
FROM Table
JOIN (
   SELECT x.value(N'.',N'uniqueidentifier') as guid
   FROM @values.nodes(N'/guids/guid') t(x)) as guids
 ON Table.guid = guids.guid;

答案 1 :(得分:36)

公开了SQL Server最大值http://msdn.microsoft.com/en-us/library/ms143432.aspx(这是2008版本)

SQL查询可以是varchar(max),但显示为限制为65,536 *网络数据包大小,但即使这样,最有可能使您绊倒的是每个查询2100个参数。如果SQL选择参数化in子句中的文字值,我认为你会先达到这个限制,但我没有测试过。

编辑:测试它,即使在强制参数化下它幸存下来 - 我敲了一个快速测试并让它在In子句中执行30k项目。 (SQL Server 2005)

在10万件物品上花了一些时间然后掉了下来:

  

Msg 8623,Level 16,State 1,Line 1   查询处理器耗尽了内部资源,无法生成查询计划。这是一种罕见的事件,仅适用于引用大量表或分区的极其复杂的查询或查询。请简化查询。如果您认为自己错误地收到了此消息,请与客户支持服务部​​门联系以获取更多信息。

所以30k是可能的,但仅仅因为你可以做到 - 并不意味着你应该:)

编辑:由于其他问题而继续。

50k工作了,但是60k退出了,所以在我的测试台上的某个地方顺便说一下。

关于如何在不使用大的in子句的情况下连接值,我个人会创建一个临时表,将值插入到临时表中,对其进行索引然后在连接中使用它,给它优化联接的最佳机会。 (在临时表上生成索引将为其创建统计数据,这将有助于优化器作为一般规则,尽管1000 GUID不会完全找到非常有用的统计数据。)

答案 2 :(得分:12)

每批,65536 * Network Packet Size,这是4k,所以256 MB

但是,IN会在此之前停止,但这不准确。

您最终会遇到内存错误,但我无法回想起确切的错误。 无论如何,巨大的IN效率低下。

编辑:Remus提醒我:错误是关于“堆栈大小”

答案 3 :(得分:7)

您可以将GUID加载到临时表中,然后执行

... WHERE var IN SELECT guid FROM #scratchtable