获得最大 SQL Server 2012 写入性能的 C# 代码

标签 c# sql sql-server performance

我想知道我们的应用程序是否已经获得了最快的 SqlSever 写入性能。

我们创建了一个示例应用程序,它对本地 SQL Server 数据库执行 BulkCopy 操作。 BulkCopy 操作从内存中的 DataTable 写入 100,000 行数据。插入的表没有索引。这是因为我们只想获得SQL Server的最大写入速度。

这是我们要插入的表的架构:

CREATE TABLE [dbo].[HistorySampleValues](
[HistoryParameterID] [bigint] NOT NULL,
[SourceTimeStamp] [datetime2](7) NOT NULL,
[ArchiveTimestamp] [datetime2](7) NOT NULL,
[ValueStatus] [int] NOT NULL,
[ArchiveStatus] [int] NOT NULL,
[IntegerValue] [int] SPARSE  NULL,
[DoubleValue] [float] SPARSE  NULL,
[StringValue] [varchar](100) SPARSE  NULL,
[EnumNamedSetName] [varchar](100) SPARSE  NULL,
[EnumNumericValue] [int] SPARSE  NULL,
[EnumTextualValue] [varchar](256) SPARSE  NULL
) ON [PRIMARY]

我们通过 C# 代码衡量性能。

public double PerformBulkCopy()
    {
        DateTime timeToBulkCopy = DateTime.Now;
        double bulkCopyTimeSpentMs = -1.0;

        DataTable historySampleValuesDataTable = CreateBulkCopyRecords();

        //start the timer here
        timeToBulkCopy = DateTime.Now;
        using (SqlConnection sqlConn = ConnectDatabase())
        {
            sqlConn.Open();

            using (SqlTransaction sqlTransaction = sqlConn.BeginTransaction())
            {
                try
                {
                    using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.KeepIdentity, sqlTransaction))
                    {
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_HISTORY_PARMETER_ID, SqlServerDatabaseStrings.SQL_FIELD_HISTORY_PARMETER_ID);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_SOURCE_TIMESTAMP, SqlServerDatabaseStrings.SQL_FIELD_SOURCE_TIMESTAMP);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_VALUE_STATUS, SqlServerDatabaseStrings.SQL_FIELD_VALUE_STATUS);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_ARCHIVE_STATUS, SqlServerDatabaseStrings.SQL_FIELD_ARCHIVE_STATUS);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_INTEGER_VALUE, SqlServerDatabaseStrings.SQL_FIELD_INTEGER_VALUE);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_DOUBLE_VALUE, SqlServerDatabaseStrings.SQL_FIELD_DOUBLE_VALUE);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_STRING_VALUE, SqlServerDatabaseStrings.SQL_FIELD_STRING_VALUE);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_ENUM_NAMEDSET_NAME, SqlServerDatabaseStrings.SQL_FIELD_ENUM_NAMEDSET_NAME);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_ENUM_NUMERIC_VALUE, SqlServerDatabaseStrings.SQL_FIELD_ENUM_NUMERIC_VALUE);
                        sqlBulkCopy.ColumnMappings.Add(SqlServerDatabaseStrings.SQL_FIELD_ENUM_TEXTUAL_VALUE, SqlServerDatabaseStrings.SQL_FIELD_ENUM_TEXTUAL_VALUE);

                        sqlBulkCopy.DestinationTableName = SqlServerDatabaseStrings.SQL_TABLE_HISTORYSAMPLEVALUES;

                        sqlBulkCopy.WriteToServer(historySampleValuesDataTable);
                    }

                    sqlTransaction.Commit();
                    //end the timer here
                    bulkCopyTimeSpentMs = DateTime.Now.Subtract(timeToBulkCopy).TotalMilliseconds;
                }
                catch (Exception ex)
                {
                    sqlTransaction.Rollback();
                }

                CleanUpDatabase(sqlConn);
            }
            sqlConn.Close();
        }

        return bulkCopyTimeSpentMs;
    }

我尝试了 SqlBulkCopy.WriteToServer() 的不同重载:DataTable、DataReader 和 DataRow[]。

在具有此规范的机器上: I3-2120 CPU @ 3.30GHz 8GB 内存 希捷酷鱼 7200.12 ST3500413AS 500GB 7200 转

我使用不同的重载获得每秒插入 ~150K-160K 行的吞吐量。

顺便说一句,我没有在测量中包括 DataTable 的创建,因为我只是想获得 SQLBulkCopy 的实际性能作为基准。

我现在要问,给定我们的示例数据和示例表,这是我们可以从 SQL Server SE 中获得的最多吗?或者我们可以做些什么来加快速度?

如果您需要有关我们设置的更多信息,请告诉我

最佳答案

SSIS 和 bcp 实用程序的性能会更好。

如果您必须使用 SqlBulkCopy,请确保您已经掌握了所有基础知识:禁用索引和触发器、切换到简单或批量加载恢复模型以最小化 tlog、表上的 x-lock 等等。还要微调 BatchSize 属性(取决于您的数据,它可能是 100 到 5000 之间的值),也许还有 UseInternalTransaction。

这是您可能会发现有用的 MSDN 链接:

http://msdn.microsoft.com/en-us/library/ms190421.aspx

关于获得最大 SQL Server 2012 写入性能的 C# 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23212333/

相关文章:

c# - 多个 RadioButtonList 并插入到 SQL 中

sql - sql 到 linq 中的 if 存在语句

sql-server - 为什么如果表中不存在列,MS Sql Server 会在表不存在时引发错误之前引发错误?

c# - C# 中的遗传编程

c# - 如何使用SSIS包从网站url下载文件

c# - 如何加快 Raven DB 查询性能?

mysql - 选择具有特定值的行之后的行

c# - 使用 Ninject 开放泛型和 IEnumerable

mysql - 如何将位数据类型的所有位填充为 1?

mysql - 何时使用 SQL 数据库中什么类型的表关系