.net 使用SQLBulkCopy—SQL Server 2016中的表比SQL Server 2014中的表大得多
我有一个应用程序,它使用SqlBulkCopy将数据移动到一组表中。最近有消息称,使用SQL2016的用户报告其硬盘驱动器中充满了非常大的数据库(不应该那么大)的问题。此问题在SQL2014中不会出现。经检查,运行TableDataSizes.sql(附脚本)显示未使用的SpaceKB中有大量空间 我想知道a)SQLServer2016中是否存在一些缺陷,或者我们对SQLBulkCopy的使用是否与新功能“冲突”。我注意到SQLServer2016中的页面分配有一些变化。一般来说,这是什么原因造成的 复制步骤 注意–以下描述了我看到的一种情况,其中删除了非必要信息。实际上,我并没有在数据库表中存储数千个时间戳(其他列已被删除).net 使用SQLBulkCopy—SQL Server 2016中的表比SQL Server 2014中的表大得多,.net,sql-server,sql-server-2014,sql-server-2016,sqlbulkcopy,.net,Sql Server,Sql Server 2014,Sql Server 2016,Sqlbulkcopy,我有一个应用程序,它使用SqlBulkCopy将数据移动到一组表中。最近有消息称,使用SQL2016的用户报告其硬盘驱动器中充满了非常大的数据库(不应该那么大)的问题。此问题在SQL2014中不会出现。经检查,运行TableDataSizes.sql(附脚本)显示未使用的SpaceKB中有大量空间 我想知道a)SQLServer2016中是否存在一些缺陷,或者我们对SQLBulkCopy的使用是否与新功能“冲突”。我注意到SQLServer2016中的页面分配有一些变化。一般来说,这是什么原因造
Public Class Form1
Private conStr As String = "Integrated Security=true;Persist Security Info=true;Server=.;Database=TestDB;Pooling=True"
Dim tableName As String = "TestTable"
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
Dim table as DataTable = GetData(nupRecordsToInsert.Value)
Using conn As SqlConnection = New SqlConnection(conStr)
conn.Open()
Using sbc As SqlBulkCopy = New SqlBulkCopy(conStr, SqlBulkCopyOptions.UseInternalTransaction Or SqlBulkCopyOptions.KeepIdentity)
sbc.DestinationTableName = "[" & tableName & "]"
sbc.BatchSize = 1000
sbc.WriteToServer(table)
End Using
End Using
MessageBox.Show($"Records Inserted = {nupRecordsToInsert.Value} into Database - TestDB. Table - {tableName}")
End Sub
Private Function GetData(numOfRecordsNeeded As Integer) As DataTable
Dim table As DataTable = New DataTable()
table.Columns.Add("TimeStamp", GetType(DateTime))
Dim dtDateTimeToInsert as DateTime = DateTime.Now
For index As Integer = 1 To numOfRecordsNeeded
dtDateTimeToInsert = dtDateTimeToInsert.AddSeconds(2)
table.Rows.Add(dtDateTimeToInsert)
Next
Return table
End Function
末级use [TestDB]
SELECT
t.NAME AS TableName,
s.Name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.NAME = 'TestTable'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows
ORDER BY
RowCounts desc
select * from sys.dm_db_database_page_allocations
(DB_id() , object_id('[dbo].[TestTable]') , NULL , NULL , 'DETAILED')
SQL2014中的数据库没有显示此问题 1.当运行适当的查询(如上所述)时,我们在UnusedSpaceKB列中没有看到大的值
use [TestDB]
SELECT
t.NAME AS TableName,
s.Name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM
sys.tables t
INNER JOIN
sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN
sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.NAME = 'TestTable'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows
ORDER BY
RowCounts desc
您是否检查了两台服务器上的服务器填充因子是否相同?您的创建索引没有明确指定它,因此使用了服务器默认值。另外,为什么不在大容量复制之后创建索引?现在这样做,您将永远不会有最小的日志记录。您使用的大容量复制几乎是最低效的方式—您有一个聚集索引o在表中,批量大小为1000且正在使用行锁而不是表锁。您仍将获得流式数据,但操作本身将被完全记录。但是,从SQL Server 2014开始,这一点本身不应改变。这两种情况下的恢复模型是否相同?是否应用了任何自定义跟踪标志?(与跟踪标志610类似,跟踪标志610支持对具有聚集索引的表上的批量插入进行最小日志记录)?数据库的自动增长设置是什么?移动了多少数据?太大是什么意思?这个问题中的步骤太模糊,无法重现任何问题一个范围是8页。看起来每个页面分配都是从一个新的范围完成的。如前所述,尝试增加批处理大小(文章还提到TF 692是一个解决方案,如果您不能的话)。(另外,很高兴知道SQL Server 2016不再需要TF 610来在聚集索引上获得最小日志批量插入。)请注意,对于批量插入来说,批量插入将始终是优化的,对于足够小的批处理,您可以考虑在事务中切换到常规插入,这不会慢得多。您是否检查了两个服务器上的服务器填充因子是否相同?您的创建索引没有明确地指定它,因此使用服务器默认值。为什么不在大容量复制之后创建索引?现在这样做,您将永远不会有最小的日志记录。您正在以几乎最低效的方式使用大容量复制--您的表上有一个聚集索引,批量大小为1000,并且使用行锁而不是表锁。您仍然会获得流式数据,但操作本身将是f完全记录。但是,这本身不应该从SQL Server 2014更改。是否恢复
select * from sys.dm_db_database_page_allocations
(DB_id() , object_id('[dbo].[TestTable]') , NULL , NULL , 'DETAILED')