【问题标题】:UPDATE faster in SQLite + BEGIN TRANSACTION在 SQLite + BEGIN TRANSACTION 中更新更快
【发布时间】:2014-08-18 03:38:02
【问题描述】:

这个也与 spatilite 相关(不仅是 SQLite)

我有一个 文件数据库 (xyz.db),SQLiteconnection 正在使用它(SQLiteconnection 扩展到了 spatialite)。

我有很多记录需要更新到数据库中。

                for (int y = 0; y < castarraylist.Count; y++)
                {
                    string s = Convert.ToString(castarraylist[y]);

                    string[] h = s.Split(':');

                    SQLiteCommand sqlqctSQL4 = new SQLiteCommand("UPDATE temp2 SET GEOM = " + h[0] + "WHERE " + dtsqlquery2.Columns[0] + "=" + h[1] + "", con);
                    sqlqctSQL4.ExecuteNonQuery();

                    x = x + 1;
                }

在上面的逻辑castarraylistArraylist,其中包含需要处理到数据库中的值。

当我检查上面的代码时,1 分钟内更新了大约 400 条记录。

有什么方法可以提高性能吗?

注意 ::(文件数据库不是线程安全的)

2。开始交易

假设我喜欢在 Spatialite 中使用单个事务运行两个(或数百万个)更新语句。这可能吗?

我在线阅读并为我准备了以下声明(但没有成功)

BEGIN TRANSACTION;
UPDATE builtuparea_luxbel SET ADMIN_LEVEL = 6 where PK_UID = 2;
UPDATE builtuparea_luxbel SET ADMIN_LEVEL = 6 where PK_UID = 3;
COMMIT TRANSACTION; 

以上语句未更新我的数据库中的记录。 SQLite 不支持 BEGIN TRANSACTION 吗? 有什么我想念的吗?

如果我需要运行单个语句,那么如上所述更新需要花费太多时间......

【问题讨论】:

    标签: c# sql sqlite spatialite


    【解决方案1】:

    SQLite 支持事务,你可以试试下面的代码。

    using (var cmd = new SQLiteCommand(conn))
    using (var transaction = conn.BeginTransaction())
    {
        for (int y = 0; y < castarraylist.Count; y++)
        {
            //Add your query here.
            cmd.CommandText = "INSERT INTO TABLE (Field1,Field2) VALUES ('A', 'B');";
            cmd.ExecuteNonQuery();
        }
        transaction.Commit();
    }
    

    【讨论】:

    • 这个逻辑和上面的有什么不同?因为这里我们也运行 for 循环,它循环了 1000 次
    • 你可以看到上面的查询将对castarraylist中的所有记录执行,完成后事务将提交,你可以试试上面的代码看看结果。
    • 是的,它有所改进,但仍然无效。对于 100000 条记录,它需要 > 50 分钟。所以我手动收集了执行每组 5000 条记录的时间。我注意到它在增加每一束的时间。 5000 条记录处理时间 1st > 1:11 分钟 2nd > 1:25 分钟 3rd > 1:32 分钟 4th > 1:40 分钟 5th > 1:47 分钟 6th > 1:52 分钟 ... ... 17th > 18 日 3:32 分钟 > 19 日 3:44 分钟 > 20 日 4:02 分钟 > 4:56 分钟 为什么会这样?需要运行其他一些内存增量命令吗?
    • 你不应该重复使用 SQLiteCommand 对象来执行如此重要的查询:它会导致内存开销。
    【解决方案2】:
    • 数据库事务的主要目标完成所有事情,如果内部出现故障,则什么都不做

    • 重复使用相同的 SQLiteCommand 对象,通过更改其 CommandText 属性并一次又一次地执行它可能会更快,但 会导致内存开销:如果您有要执行的查询量很大,最好是在使用后处理对象并创建一个新对象;

    ADO.NET 事务的常见模式是:

    using (var tra = cn.BeginTransaction())
    {
        try
        { 
            foreach(var myQuery in myQueries)
            { 
                using (var cd = new SQLiteCommand(myQuery, cn, tra))
                {
                    cd.ExecuteNonQuery();
                }
            }
    
            tra.Commit();
        }
        catch(Exception ex)
        {
            tra.Rollback();
            Console.Error.Writeline("I did nothing, because something wrong happened: {0}", ex);
            throw;
        }
    }
    

    【讨论】:

    • 你怎么知道它会导致内存开销?
    • 任务管理器中的私有内存使用情况。当我正确处理 SQLiteCommand 时,它不会发生。 This behavior has been also seen here。还有here。顺便说一句,如果有解决方案,我很感兴趣:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多