表值构造函数选择中的最大行数限制

时间:2016-11-07 08:23:03

标签: sql sql-server sql-server-2012 bulkupdate

我有一个Table Valued Constructor,我可以选择约1 million个记录。它将用于update另一个表。

SELECT *
FROM   (VALUES (100,200,300),
               (100,200,300),
               (100,200,300),
               (100,200,300),
               .....
               ..... --1 million records
               (100,200,300)) tc (proj_d, period_sid, val) 

以下是我的原始查询:https://www.dropbox.com/s/ezomt80hsh36gws/TVC.txt?dl=0#

当我执行上述select时,只显示查询已完成但错误并显示任何错误消息。

enter image description here

更新:尝试使用TRY/CATCH阻止捕获错误消息或错误编号,但不使用与上一个图像相同的错误

BEGIN try
    SELECT *
    FROM   (VALUES (100,200,300),
                    (100,200,300),
                    (100,200,300),
                    (100,200,300),
                    .....
                    ..... --1 million records
                    (100,200,300)) tc (proj_d, period_sid, val) 
END try

BEGIN catch
    SELECT Error_number(),
           Error_message()
END catch 

为什么它没有执行,Select中的表Valed构造函数有任何限制。我知道Insert它是1000,但我在这里选择。

2 个答案:

答案 0 :(得分:3)

没有相关的硬编码限制(65,536 * 4KB的网络数据包大小为268 MB且您的脚本长度远不及那个),但不建议将此方法用于大量行。

您看到的错误是客户端工具而不是SQL Server引发的。如果在动态SQL中构造SQL字符串,则编译能够至少成功启动

DECLARE @SQL NVARCHAR(MAX) = '(100,200,300),
';

SELECT @SQL = 'SELECT * FROM (VALUES ' + REPLICATE(@SQL, 1000000) + '
(100,200,300)) tc (proj_d, period_sid, val)';

SELECT @SQL AS [processing-instruction(x)]
FOR XML PATH('')

SELECT DATALENGTH(@SQL) / 1048576.0 AS [Length in MB] --30.517705917

EXEC(@SQL);

虽然我在编制时间约30分钟后杀了上述内容,但仍然没有产生一排。文字值需要作为常量表存储在计划本身内,SQL Server花费a lot of time试图获取有关它们的属性。

SSMS是一个32位应用程序,在解析批处理时抛出std::bad_alloc异常

enter image description here

它尝试将元素推送到已达到容量的令牌向量,并且由于无法获得足够大的连续内存区域而导致其调整大小失败。所以声明从来没有使它成为服务器。

每次矢量容量增加50%(即the sequence here之后)。向量需要增长的容量取决于代码的布局方式。

以下需要从19到28的容量增长。

SELECT * FROM 
(VALUES 
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300)) tc (proj_d, period_sid, val)

以下只需要2的大小

SELECT * FROM (VALUES (100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300)) tc (proj_d, period_sid, val)

以下需要<>的容量。 63和&lt; = 94。

SELECT *
FROM   (VALUES 
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300)
       ) tc (proj_d, period_sid, val) 

如案例1中所列出的一百万行,载体容量需要增加到3,543,306。

您可能会发现以下任何一种情况都会允许客户端解析成功。

  1. 减少换行次数。
  2. 重新启动SSMS,希望在地址空间碎片较少时,对大型连续内存的请求成功。
  3. 然而,即使你成功地将它发送到服务器,它也只会在执行计划生成过程中终止服务器,如上所述。

    使用导入导出向导加载表格会好得多。如果您必须在TSQL中执行此操作,您会发现将其分成较小的批次和/或使用其他方法(如shreding XML)将比Table Valued Constructors表现更好。例如,以下命令在我的机器上执行13秒(尽管如果使用SSMS,您仍然可能需要分成多个批次而不是粘贴大量的XML字符串文字)。

    DECLARE @S NVARCHAR(MAX) = '<x proj_d="100" period_sid="200" val="300" />
    ' ; 
    
    DECLARE @Xml XML = REPLICATE(@S,1000000);
    
    SELECT 
        x.value('@proj_d','int'),
        x.value('@period_sid','int'),
        x.value('@val','int')
    FROM @Xml.nodes('/x') c(x)
    

答案 1 :(得分:0)