C#操作SQL Server 2022插入1000行耗时10秒,求慢因排查
1000行SQL Server插入耗时10秒:速度异常及原因分析
这个速度完全不正常
正常情况下,插入1000行这类简单数据到SQL Server,耗时应该在几百毫秒以内,10秒属于严重异常,核心问题集中在你的C#代码实现逻辑上。
异常缓慢的核心原因
- 频繁开闭数据库连接+单条独立事务:你的
SqlExecuteNonQuery方法每次插入后都关闭连接,即便有连接池复用,频繁的开闭操作仍会产生额外开销。更关键的是,每一行INSERT都是独立事务,数据库需要为每一行执行日志写入、锁管理等操作,这是最大的性能消耗点。 - 逐行发送INSERT请求:循环里每一行都单独发送一条SQL请求到数据库,1000次请求意味着1000次网络往返,加上SQL Server对每条语句的解析、编译开销,累加后直接拉低了整体速度。
- 未使用参数化查询:用字符串拼接生成SQL语句,导致SQL Server无法重用执行计划,每次都要重新编译SQL,进一步增加了执行成本。
优化方案(快速解决)
方案1:用事务包裹所有插入
将所有插入操作放在一个事务中,减少事务日志的频繁写入:
private void button1_Click(object sender, EventArgs e) { try { if (conn.State == ConnectionState.Closed) conn.Open(); using (var transaction = conn.BeginTransaction()) { for (int i = 1000; i < 2000; i++) { string query = $"INSERT INTO dbo.DB(CODE) VALUES('CHOCO{i}')"; using (SqlCommand cmd = new SqlCommand(query, conn, transaction)) { cmd.ExecuteNonQuery(); } } transaction.Commit(); } } catch (Exception ex) { // 异常处理逻辑 } finally { if (conn.State == ConnectionState.Open) conn.Close(); } }
方案2:参数化批量插入(推荐)
避免字符串拼接,同时复用执行计划,进一步降低开销:
private void button1_Click(object sender, EventArgs e) { try { if (conn.State == ConnectionState.Closed) conn.Open(); using (var transaction = conn.BeginTransaction()) { string query = "INSERT INTO dbo.DB(CODE) VALUES(@Code)"; using (SqlCommand cmd = new SqlCommand(query, conn, transaction)) { var codeParam = cmd.Parameters.Add("@Code", SqlDbType.VarChar, 20); for (int i = 1000; i < 2000; i++) { codeParam.Value = $"CHOCO{i}"; cmd.ExecuteNonQuery(); } } transaction.Commit(); } } catch (Exception ex) { // 异常处理逻辑 } finally { if (conn.State == ConnectionState.Open) conn.Close(); } }
方案3:SqlBulkCopy(最优性能)
针对大量数据插入,SqlBulkCopy是SQL Server提供的最高效批量写入方式:
private void button1_Click(object sender, EventArgs e) { // 构造要插入的数据集 DataTable dt = new DataTable(); dt.Columns.Add("CODE", typeof(string)); for (int i = 1000; i < 2000; i++) { dt.Rows.Add($"CHOCO{i}"); } try { if (conn.State == ConnectionState.Closed) conn.Open(); using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, null)) { bulkCopy.DestinationTableName = "dbo.DB"; bulkCopy.ColumnMappings.Add("CODE", "CODE"); bulkCopy.WriteToServer(dt); } } catch (Exception ex) { // 异常处理逻辑 } finally { if (conn.State == ConnectionState.Open) conn.Close(); } }
内容的提问来源于stack exchange,提问作者maru
相关产品推荐
相关产品推荐

