我有以下代码,它工作正常。我的问题是插入花了三个多小时。
如何在sql表中优化插入查询?
foreach(var sheetName in GetExcelSheetNames(connectionString)) {
using(OleDbConnection con1 = new OleDbConnection(connectionString)) {
var dt = new DataTable();
string query = string.Format("SELECT * FROM [{0}]", sheetName);
con1.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con1);
adapter.Fill(dt);
using(SqlConnection con = new SqlConnection(consString)) {
con.Open();
for (int i = 2; i < dt.Rows.Count; i++) {
for (int j = 1; j < dt.Columns.Count; j += 3) {
try {
var s = dt.Rows[i][0].ToString();
var dt1 = DateTime.Parse(s, CultureInfo.GetCultureInfo("fr-FR"));
var s1 = dt.Rows[i][j].ToString();
var s2 = dt.Rows[i][j + 1].ToString();
var s3 = sheetName.Remove(sheetName.Length - 1);
{
SqlCommand command = new SqlCommand("INSERT INTO [Obj CA MPX] ([CA TTC],[VAL MRG TTC],[CA HT],[VAL MRG HT],[Rayon],[Date],[Code Site]) VALUES(@ca,@val,@catHT ,@valHT ,@rayon, @date ,@sheetName )", con);
command.Parameters.Add("@date", SqlDbType.Date).Value = dt1;
command.Parameters.AddWithValue("@ca", s1);
command.Parameters.AddWithValue("@val", s2);
command.Parameters.AddWithValue("@rayon", dt.Rows[0][j].ToString());
command.Parameters.AddWithValue("@sheetName", s3);
command.Parameters.Add("@catHT", DBNull.Value).Value = DBNull.Value;
command.Parameters.Add("@valHT", DBNull.Value).Value = DBNull.Value;
command.ExecuteNonQuery();
}
}
}
答案 0 :(得分:1)
也许您应该将其保存为文件并使用批量插入
https://msdn.microsoft.com/de-de/library/ms188365%28v=sql.120%29.aspx
答案 1 :(得分:0)
SQL Server可以选择使用Bulk Insert。
Here是关于导入csv的好文章。
答案 2 :(得分:0)
您应首先阅读Eric Lippert撰写的这篇文章:Which is faster? 在尝试优化流程时请记住这一点。
插入花了3个小时,但是你插入了10个物品还是900.000.000.000个物品? 如果它是最后一个,那么3个小时就可以了。
你的数据库是什么? SQL Server 2005 Express? SQL Server 2014企业版? 建议可能有所不同。
如果没有更多详细信息,我们只能根据您的配置向您提供可能适用或不适用的建议 以下是我头脑中的一些内容:
AddWithValue
,它可以阻止您在查询中使用索引BULKED_LOGGED
,或者您可以激活SIMPLE恢复模式(alter database [YourDB] set recovery SIMPLE
,不要忘记重新启用FULL
恢复模式)此列表可以永久持续。
这是一篇关于优化数据加载的有趣文章:We Loaded 1TB in 30 Minutes with SSIS, and So Can You
本文主要关注SSIS,但有些建议并不仅适用于它。
答案 3 :(得分:0)
您可以使用字符串构建器将多个(例如100个)插入到字符串中。使用参数名称的索引。请注意,一个查询最多可以包含2100个参数。
StringBuilder batch = new StringBuilder();
for (int i = 0; i < pageSize; i++)
{
batch.AppendFormat(
@"INSERT INTO [Obj CA MPX] ([CA TTC],[VAL MRG TTC], ...) VALUES(@ca{0},@val{0}, ...)"
i);
batch.AppendLine();
batch.AppendLine();
}
SqlCommand command = new SqlCommand(batch.ToString(), con)
// append parameters, using the index
for (int i = 0; i < pageSize; i++)
{
command.Parameters.Add("@date" + i, SqlDbType.Date).Value = dt1[i];
command.Parameters.AddWithValue("@ca" + i, s1[i]);
// ...
}
command.ExecuteNonQuery();
当然这还没有完成,你必须将页面集成到你现有的循环中,这可能不会太简单。
或者,您不使用参数并将参数直接放入查询中。这样,您可以创建更大的批次(我会在一个批次中放置1000到10000个插入),并且它更容易实现。