2009-12-08 127 views
82

可能重复:
T-SQL WHERE col IN (…)SQL Server查询的最大大小? IN子句?有没有更好的办法

什么是一个SQL Server查询的最大尺寸是多少? (字符数)

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

UPDATE 那么这将是最好的办法,如果我需要从其他系统(非关系数据库)说,1000点的GUID并做代码”对SQL Server中的“加入?是不是提交列表1000个GUID来IN子句? 还是那里的工作更有效率的另一种技术?

我没有测试过这一点,但我想如果我能提交的GUID作为XML文档。例如

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

然后做一些XQuery JOIN反对文件和表格。效率低于1000条IN子句?

+1

似乎是一个重复:HTTP://计算器。 com/questions/1069415/t-sql-where-col-in – Yishai 2009-12-08 20:57:26

+0

让我补充一点,让它更独特。看到更新 – BuddyJoe 2009-12-08 21:08:12

+1

资源我发现讨论一些想法 - http://www.sommarskog.se/arrays-in-sql-2005.html#InsertMany – BuddyJoe 2009-12-08 21:26:42

回答

64

每个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),所以它可能会非常深入。

更新

你已经找到了通过列表/阵列到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; 
+0

“堆栈大小”:这是我记不清的错误 – gbn 2009-12-08 21:02:51

12

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

然而,在将停止的方式在此之前,但它不是精确的。

您最终出现内存错误,但我无法记起确切的错误。 无论如何,巨大的IN将效率低下。

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

34

的SQL Server最大披露http://msdn.microsoft.com/en-us/library/ms143432.aspx(这是2008年版)

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

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

在100K的项目,花了一些时间,然后与下降:

消息8623,级别16,状态1,行 查询处理器用尽了内部资源,不能产生一个查询计划。这是一个罕见的事件,并且只能用于引用大量表或分区的极其复杂的查询或查询。请简化查询。如果您认为您错误地收到了此消息,请联系客户支持服务以获取更多信息。

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

编辑:由于额外的问题持续。

50k工作,但60k退出,所以在我的测试平台btw的某处。

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

+1

看到更新。谢谢你的测试+1 – BuddyJoe 2009-12-08 21:12:59

+0

不幸的是,这些排队将定期进行。所以我不认为临时表的索引是可能的。对于最大快速插入,主表将由int'addid'索引(不会在GUID上编入索引)。这个东西比我想象的更复杂。 – BuddyJoe 2009-12-08 21:51:59

+1

您冒着轻微的过早优化的风险 - 您需要根据您的工作负载的查询计划获取一些硬装备数据,因为它很难建模。一旦你知道了各种方法的数字,你可以做出选择,但是将1k行插入到SQL临时表中可以非常快地完成,这取决于如何/如何驱动它。 – Andrew 2009-12-08 22:26:38

7

你能的GUID加载到一个临时表,然后做一个

... WHERE var IN SELECT guid FROM #scratchtable 
+0

如果您认为每隔一两秒就会有这些查询。我想知道如何保留临时表。 – BuddyJoe 2009-12-08 21:20:42

+2

我们在我们的应用程序中使用这种技术extensivley,它似乎运作良好。 Tempdb需要很大,我们会对安装进行一些调整 - 我不知道这些细节。 Tempdb确实很忙。 – DaveE 2009-12-09 18:52:11

相关问题