管理大容量复制的批大小

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse AnalyticsAnalytics Platform System (PDW)

在大容量复制操作中,批的主要目的在于定义事务的范围。 如果没有设置批大小,则大容量复制函数会将整个大容量复制视为一个事务。 如果设置了批大小,则每个批构成一个事务,当批运行完成时,该事务也就被提交。

如果在没有指定批大小的情况下执行大容量复制并且遇到错误,则将回滚整个大容量复制。 恢复长时间运行的大容量复制可能需要花费很长的时间。 如果设置了批大小,则大容量复制将每个批视为一个事务并分别提交每个批。 如果遇到错误,只需回滚最后一个未完成的批。

此外,批大小还会影响锁定开销。 针对SQL Server执行大容量复制时,可以使用bcp_control指定 TABLOCK 提示来获取表锁而不是行锁。 对于整个大容量复制操作而言,持有单个表锁的开销最小。 如果未指定 TABLOCK,则对各个行持有锁,并且在大容量复制操作期间维护所有锁的开销会导致性能降低。 由于仅在事务执行期间才持有锁,因而可以通过指定批大小来解决此问题,因为这样可以定期生成能够释放当前持有的锁的提交。

如果要大容量复制大量的行,构成批的行的数目会对性能产生显著影响。 建议采用的批大小取决于要执行的大容量复制的类型。

  • 大容量复制到SQL Server时,请指定 TABLOCK 大容量复制提示并设置较大的批大小。

  • 如果不指定 TABLOCK,请将批大小限制为小于 1,000 行。

从数据文件批量复制时,批大小是通过在调用 bcp_exec 之前使用 BCPBATCH 选项调用 bcp_control来指定的。 使用 bcp_bindbcp_sendrow 从程序变量批量复制时,批大小通过在调用 bcp_sendrowx 次后调用 bcp_batch来控制,其中 x 是批中的行数。

除了指定事务大小之外,批还会影响将行通过网络发送到服务器的时间。 大容量复制函数通常缓存 bcp_sendrow 中的行,直到填充网络数据包,然后将完整数据包发送到服务器。 但是,当应用程序调用 bcp_batch时,无论当前数据包是否已填充,都会将当前数据包发送到服务器。 使用很小的批大小可能导致向服务器发送许多部分填满的数据包,从而降低性能。 例如,在每次 bcp_sendrow 后调用 bcp_batch 会导致每行在单独的数据包中发送,并且除非行非常大,否则会浪费每个数据包中的空间。 SQL Server的网络数据包的默认大小为 4 KB,但应用程序可以通过调用指定 SQL_ATTR_PACKET_SIZE 属性的 SQLSetConnectAttr 来更改大小。

批处理的另一个副作用是,每批都被视为未完成的结果集,直到完成 bcp_batch。 如果在批处理未完成时尝试对连接句柄执行任何其他操作,SQL Server Native Client ODBC 驱动程序将发出 SQLState = “HY000” 的错误和错误消息字符串:

"[Microsoft][SQL Server Native Client] Connection is busy with  
results for another hstmt."  

另请参阅

执行大容量复制操作 (ODBC)
大容量导入和导出数据 (SQL Server)