首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DataAdapter.Update()性能

DataAdapter.Update()性能
EN

Stack Overflow用户
提问于 2015-07-08 08:30:45
回答 2查看 4.8K关注 0票数 4

我有一个相对简单的例程,它查看数据库条目中的媒体文件,计算宽度、高度和文件大小,然后将它们写回数据库。

数据库是SQLite,使用System.Data.SQLite库处理~4000行。我将所有行加载到ADO表中,用新值更新行/列,然后在其上运行adapter.Update( table );。

从db表加载数据集大约需要半秒钟,用图像宽度/高度更新所有行并从FileInfo获取文件长度可能需要30秒。很好。

Adapter.Update(表);命令在5到7分钟左右运行。

这似乎太过分了。ID是一个PK整数,因此--根据SQLite的文档,它是固有的索引,但是即便如此,我还是忍不住认为,如果我要为每个单独的更新运行一个单独的更新命令,完成速度就会快得多。

我曾认为ADO/适配器级别相对较低(与ORMs不同),这种糟糕的性能让我感到惊讶。有人能解释一下为什么需要5-7分钟才能根据本地的SQLite数据库更新一批~4000条记录吗?

顺便说一句,是否有办法“窥探”ADO是如何处理这一问题的?内部图书馆的步骤还是.?

谢谢

代码语言:javascript
复制
public static int FillMediaSizes() {
        // returns the count of records updated

        int recordsAffected = 0;

        DataTable table = new DataTable();
        SQLiteDataAdapter adapter = new SQLiteDataAdapter();

        using (SQLiteConnection conn = new SQLiteConnection(Globals.Config.dbAppNameConnectionString))
        using (SQLiteCommand cmdSelect = new SQLiteCommand())
        using (SQLiteCommand cmdUpdate = new SQLiteCommand()) {

            cmdSelect.Connection = conn;
            cmdSelect.CommandText =
                "SELECT ID, MediaPathCurrent, MediaWidth, MediaHeight, MediaFilesizeBytes " +
                "FROM Media " +
                "WHERE MediaType = 1 AND (MediaWidth IS NULL OR MediaHeight IS NULL OR MediaFilesizeBytes IS NULL);";

            cmdUpdate.Connection = conn;
            cmdUpdate.CommandText =
                "UPDATE Media SET MediaWidth = @w, MediaHeight = @h, MediaFilesizeBytes = @b WHERE ID = @id;";

            cmdUpdate.Parameters.Add("@w", DbType.Int32, 4, "MediaWidth");
            cmdUpdate.Parameters.Add("@h", DbType.Int32, 4, "MediaHeight");
            cmdUpdate.Parameters.Add("@b", DbType.Int32, 4, "MediaFilesizeBytes");
            SQLiteParameter param = cmdUpdate.Parameters.Add("@id", DbType.Int32);
            param.SourceColumn = "ID";
            param.SourceVersion = DataRowVersion.Original;

            adapter.SelectCommand = cmdSelect;
            adapter.UpdateCommand = cmdUpdate;

            try {
                conn.Open();
                adapter.Fill(table);
                conn.Close();
            }
            catch (Exception e) {
                Core.ExceptionHandler.HandleException(e, true);
                throw new DatabaseOperationException("", e);
            }

            foreach (DataRow row in table.Rows) {

                try {

                    using (System.Drawing.Image img = System.Drawing.Image.FromFile(row["MediaPathCurrent"].ToString())) {

                        System.IO.FileInfo fi;

                        fi = new System.IO.FileInfo(row["MediaPathCurrent"].ToString());

                        if (img != null) {

                            int width = img.Width;
                            int height = img.Height;
                            long length = fi.Length;

                            row["MediaWidth"] = width;
                            row["MediaHeight"] = height;
                            row["MediaFilesizeBytes"] = (int)length;
                        }
                    }
                }
                catch (Exception e) {
                    Core.ExceptionHandler.HandleException(e);
                    DevUtil.Print(e);
                    continue;
                }
            }                


            try {
                recordsAffected = adapter.Update(table);
            }
            catch (Exception e) {
                Core.ExceptionHandler.HandleException(e);
                throw new DatabaseOperationException("", e);
            }


        }

        return recordsAffected;
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-08 08:43:30

从db表加载数据集半秒钟左右

这是一个SQL语句(所以它很快)。执行SELECT,填充数据集,完成。

用图像宽度/高度更新所有行并从FileInfo获取文件长度可能需要30秒。很好。

这是在更新内存中的数据(所以速度也很快),在dataset中更改x行,根本不与SQL对话。

adapter.Update(table);命令运行时间大约在5到7分钟左右。

这将为每个更新的行运行一个SQL 。这就是它慢的原因。

然而,即便如此,我还是忍不住认为,如果我为每个单独的更新运行一个单独的更新命令,那么完成的速度就会快得多。

不管怎么说,这基本上就是它所做的!

来自MSDN

更新是在逐行基础上执行的。对于每个插入、修改和删除的行,Update方法确定对其执行的更改类型(插入、更新或删除)。根据更改的类型,将执行Insert、Update或Delete命令模板将修改后的行传播到数据源。当应用程序调用更新方法时,DataAdapter检查RowState属性,并根据在DataSet中配置的索引的顺序迭代执行所需的INSERT、UPDATE或DELETE语句

有没有办法“窥探”ADO是如何处理这一问题的?

是:调试Visual 2012中的.NET框架源代码?

票数 2
EN

Stack Overflow用户

发布于 2021-03-23 16:50:18

使用Connection.BeginTransaction()来加速DataAdapter更新。

代码语言:javascript
复制
conn.Open() 'open connection
Dim myTrans As SQLiteTransaction
myTrans = conn.BeginTransaction() 
'Associate the transaction with the select command object of the DataAdapter
objDA.SelectCommand.Transaction = myTrans 

objDA.Update(objDT)

Try
    myTrans.Commit()
Catch ex As Exception
    myTrans.Rollback()
End Try
conn.Close()

这大大加快了更新速度。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31287371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档