Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DataAdapter.Update()性能_C#_Performance_Sqlite_Ado.net - Fatal编程技术网

C# DataAdapter.Update()性能

C# DataAdapter.Update()性能,c#,performance,sqlite,ado.net,C#,Performance,Sqlite,Ado.net,我有一个相对简单的例程,它查看媒体文件的数据库条目,计算宽度、高度和文件大小,然后将它们写回数据库 数据库为SQLite,使用System.Data.SQLite库,处理约4000行。我将所有行加载到ADO表中,用新值更新行/列,然后运行adapter.update(table);在上面 从db表加载数据集大约需要半秒钟,使用图像宽度/高度更新所有行,并从FileInfo获取文件长度可能需要30秒。好的 适配器更新(表);命令在大约5到7分钟的时间内运行 这似乎太过分了。ID是一个PK整数,因此

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

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

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

适配器更新(表);命令在大约5到7分钟的时间内运行

这似乎太过分了。ID是一个PK整数,因此——根据SQLite的文档,它本质上是索引的,尽管如此,我还是忍不住想,如果我为每个单独的更新运行一个单独的更新命令,这将完成得更快

我曾认为ADO/适配器的级别相对较低(与ORMs相反),这种糟糕的性能让我吃惊。有人能解释一下为什么在本地放置的SQLite数据库上更新一批约4000条记录需要5-7分钟

顺便问一下,有没有办法“窥探”ADO是如何处理这个问题的?内部库步骤或

谢谢

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;
    }
半秒钟左右从db表加载数据集

这是一条SQL语句(因此速度很快)。执行SQL选择,填充数据集,完成

使用图像宽度/高度更新所有行并获取文件 文件信息的长度可能需要30秒。好的

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

adapter.Update(表)命令发生在5号附近的某个地方
要跑7分钟

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

尽管如此,我还是忍不住想,如果我要单独经营一家公司 对于每个单独的更新,这将完成更新命令 快得多

这基本上就是它正在做的


更新是按行执行的。每插入一个, “已修改”和“已删除”行的更新方法确定 对其执行的更改(插入、更新或删除)。 根据更改的类型,可以使用Insert、Update或Delete命令 执行模板以将修改的行传播到数据源。 当应用程序调用Update方法时,DataAdapter将检查 RowState属性,并执行所需的插入、更新或 根据语句的顺序,为每一行迭代删除语句 在数据集中配置的索引


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


是:

使用Connection.BeginTransaction()加速数据适配器更新

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()

这大大加快了更新速度。

回答:有没有办法“窥探”ADO是如何处理的?虽然它是从
c
的角度来看的,
sqlite
仍然是一个恒久不变的感谢。很抱歉,在询问之前,我应该能够自己找到此MSDN参考。我曾期待某种内部优化,但显然这是错误的!