【问题标题】:Insert takes too long, code optimization needed插入耗时太长,需要代码优化
【发布时间】:2010-01-22 23:46:03
【问题描述】:

我有一些代码用于将table1 值传输到另一个table2,它们位于不同的数据库中。

当我有 100.000 条记录时,它很慢。完成需要很长时间,10 多分钟。

(Windows Mobile 智能手机)

我能做什么?

cmd.CommandText = "insert into " + TableName + " select * from sync2." + TableName+"";  
cmd.ExecuteNonQuery();

编辑

问题没有解决。我还在寻找答案。

【问题讨论】:

  • 您的意思是 100.000 还是 100,000(例如,十万)?使用小数作为分隔符会让程序员(和大多数人)感到困惑
  • 目标表有索引吗?有多少行?
  • 我的意思是 100 000。目标表是空的。
  • 其实有两种情况。第一次,记录将不存在。纯插入更好,但第二次他们会,我需要插入或替换。
  • 如果目标表有聚集索引,您可能会从删除它并在插入后重新添加它中受益。

标签: c# optimization sqlite compact-framework transactions


【解决方案1】:

1]你可以在你的connectionString中设置以下参数

string connectionString = @"Data Source=E:\myDB.db3; New=true; Version=3; PRAGMA cache_size=20000; PRAGMA page_size=32768; PRAGMA synchronous=off";

它有其自身的局限性。详情请查看this link

以上内容最终会增加缓存大小(cache_size & page_size),但如果系统强制关闭,您可能会丢失一些数据(同步=关闭)。

2] 您可以将插入语句包装在这样的事务中

dbTransaction = dbConnection.BeginTransaction();
dbCommand.Transaction = dbTransaction;
// your individual insert statements here
dbTransaction.Commit();

3] 还有一个技巧在this page 中有很好的解释。看看吧

希望有帮助
干杯!

【讨论】:

  • 第二个像坏了。
【解决方案2】:

据我所知,您每行使用两个 SQL 语句 - 一个用于插入,另一个用于更新整个表。您需要更新整个表格,还是只更新您要插入的行?如果没有,您可以首先插入将dirty 设置为0 的行。

您还可以尝试将临时插入语句更改为准备好的/编译的/参数化的语句。在一些提供小幅速度提升的数据库引擎中。

SQLite 常见问题解答here 中列出了一些改进选项。

最后,你弄清楚你的瓶颈是什么了吗?我对手机应用程序的性能了解不多 - 您的分析是否显示您受 CPU 限制或“磁盘”限制,无论该特定手机上的磁盘通过什么方式?

【讨论】:

  • 完成该过程后,我必须为所有记录设置脏 0。我不知道参数化查询是否会对我有所帮助,因为表模式是可变的,而且我不知道固定列。在移动设备上,CPU 和磁盘都是瓶颈。可能磁盘更多。
【解决方案3】:

一个可能会有所帮助的建议是(尽管您需要对此进行分析),即为具有多个值的多条记录一次调用您的插入或替换命令。这将批量调用数据库,这可能会加快速度。

另外,听起来您正在从一个数据库复制到另一个数据库 - 如果新数据库中不存在记录,您可以使用 INSERT 而不是 INSERT OR REPLACE,这(至少理论上)更快。

然而,这些都不会是戏剧性的 - 这可能仍然是一个缓慢的操作。

【讨论】:

  • 据我所知 SQLite 不支持多个值。其实有两种情况。第一次,记录将不存在。纯插入更好,但第二次他们会,我需要插入或替换。
【解决方案4】:

您可以构建字符串,然后将其作为批处理一次执行,或者查看批处理更新,而不是单独执行语句。

或者,您可以将这一切作为一个可能更有效的语句来完成,我的意思是这样的:

http://forums.mysql.com/read.php?61,15029,15029

我希望这会有所帮助。

【讨论】:

  • 能否请您说的更准确一些,请继续使用 SQLite。批量更新在 sqlite 上很少见。
  • 您可以通过执行以下操作来摆脱循环:插入 ???选择 ???来自???
  • 他在处理两个不同的数据库,而不是同一个数据库中的两个表。
【解决方案5】:

您正在为每个插入使用查询处理器。使用命令,向它添加参数,准备它,然后在循环中设置参数会更好。

我不知道 SQLite 是否支持TableDirect 命令。如果确实如此,那将会更快(例如,在 SQL Compact 中要快几个数量级)。这当然值得一试。

【讨论】:

  • 根据该页面上的注释:TableDirect 仅受用于 OLE DB 的 .NET Framework 数据提供程序支持。当 CommandType 设置为 TableDirect 时,不支持多表访问。
【解决方案6】:

我认为您可以使用 DataTable(我认为 - 还是 DataSet?抱歉,仍然是 .NET 的初学者),然后将 .Fill() Reader 的结果放入 DataTable,然后有一个BulkCopyBulkInsert 操作,可以将其全部推送到另一个数据库中的表中(连接)。

【讨论】:

    【解决方案7】:
    1. 如果直接在 SQL 管理工作室执行,sql 语句是否也需要 10 分钟以上?
    2. 如果没有,您是否尝试使用 SQL 过程生成并执行它?
    3. 您是否尝试设置连接池和/或将光标设置为服务器端?
    4. 如果 1. 运行缓慢,则运行 SQL 分析器(您可以从管理工作室调用它)并在那里添加事务队列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 2011-07-21
      • 2014-08-04
      相关资源
      最近更新 更多