SqLite C#更新速度极慢

时间:2012-05-15 09:26:45

标签: c# sqlite executenonquery journal

我真的很难解决这个问题。当我使用以下代码更新我的数据库以获取大量记录时,它运行速度非常慢。我有500,000条记录要更新,这需要将近一个小时。在此操作期间,日志文件缓慢增长,主SQLite db3文件几乎没有变化 - 这是正常的吗?

当我有大量数据或记录要更新时,操作似乎只是一个问题 - 它几乎立即在较少数量的记录上运行。

在此代码运行之前,对数据库执行了一些其他操作,那么它们是否会占用数据库?我已经尝试确保所有其他连接都正确关闭。

感谢您的任何建议

using (SQLiteConnection sqLiteConnection = new SQLiteConnection("Data Source=" + _case.DatabasePath))
{
    sqLiteConnection.Open();
    using (SQLiteCommand sqLiteCommand = new SQLiteCommand("begin", sqLiteConnection))
    {
        sqLiteCommand.ExecuteNonQuery();
        sqLiteCommand.CommandText = "UPDATE CaseFiles SET areaPk = @areaPk, KnownareaPk = @knownareaPk WHERE mhash = @mhash";
        var pcatpk = sqLiteCommand.CreateParameter();
        var pknowncatpk = sqLiteCommand.CreateParameter();
        var pmhash = sqLiteCommand.CreateParameter();
        pcatpk.ParameterName = "@areaPk";
        pknowncatpk.ParameterName = "@knownareaPk";
        pmhash.ParameterName = "@mhash";
        sqLiteCommand.Parameters.Add(pcatpk);
        sqLiteCommand.Parameters.Add(pknowncatpk);
        sqLiteCommand.Parameters.Add(pmhash);
        foreach (CatItem CatItem in _knownFiless)
        {

            if (CatItem.FromMasterHashes == true)
            {
                pcatpk.Value = CatItem.areaPk;
                pknowncatpk.Value = CatItem.areaPk;
                pmhash.Value = CatItem.mhash; 
            }
            else
            {
                pcatpk.Value = CatItem.areaPk;
                pknowncatpk.Value = null;
                pmhash.Value = CatItem.mhash; 
            }
            sqLiteCommand.ExecuteNonQuery();
        }
        sqLiteCommand.CommandText = "end";
        sqLiteCommand.ExecuteNonQuery();
        sqLiteCommand.Dispose();
        sqLiteConnection.Close();
    }
    sqLiteConnection.Close();
}

4 个答案:

答案 0 :(得分:2)

确保你有mhash索引的第一件事。 将命令分组到批次中。 使用多个线程。

或[插入]

批量导入记录到临时表。在mhash列上创建索引。执行单个更新语句以更新记录。

答案 1 :(得分:0)

这部分肯定是你的问题。

foreach (CatItem CatItem in _knownFiless)
{
....
     sqLiteCommand.ExecuteNonQuery();
}

您正在循环List(?)并对数据库执行查询。这不是一个好方法。因为数据库调用非常昂贵。因此,您可以考虑使用其他方式更新这些项目。

答案 2 :(得分:0)

SQL代码似乎没问题。 C#代码没有错,但它有一些冗余(因为你已经使用了using,所以不需要显式关闭/ dispose。)

_knownFiless上有一个for循环(打算用双s?),可能会慢慢运行吗?在针对数据库的for循环中运行查询是很常见的,而应该使用相应的参数集创建查询。考虑一下(特别是没有哈希索引)你将执行n * m次操作(n是for循环的运行次数,m是表的大小)。

考虑到m大约为500k,假设m = n,你将获得250,000,000,000次操作。这可能持续一个小时。

据我所知,以前的连接或操作应该没有效果。

您还应确保数据库的内部结构不会导致问题。是否存在受此操作影响的复合索引?任何外键/复杂的约束?

答案 3 :(得分:0)

你需要将所有东西都包装在一个事务中,否则我相信SQLite会为每次更新创建并提交一个...因此速度很慢。您清楚地知道查看您的代码但我不确定使用“开始”和“结束”命令在此处实现相同的结果,您可能最终在开始和结束时使用空事务而不是包装所有内容。尝试这样的事情,以防万一:

  using (SQLiteTransaction mytransaction = myconnection.BeginTransaction())
  {
    using (SQLiteCommand mycommand = new SQLiteCommand(myconnection))
    {
      SQLiteParameter myparam = new SQLiteParameter();

      mycommand.CommandText = "YOUR QUERY HERE";
      mycommand.Parameters.Add(myparam);

      foreach (CatItem CatItem in _knownFiless)
      {
        ...
        mycommand.ExecuteNonQuery();
      }
    }
    mytransaction.Commit();
  }