为什么SQLite插入会非常慢? (使用的交易)

时间:2011-12-01 10:35:46

标签: c# .net sql sqlite

我在SQLite数据库中插入了8500行。 Core 2 Duo需要> 30sec。 在此期间它使用70%的CPU,那么问题就是CPU使用率。

我正在使用交易。

我在临时文件中动态创建数据库,表格和插入内容。然后我不必担心腐败等等。

我只是尝试使用它,但没有帮助:

PRAGMA journal_mode = OFF;
PRAGMA synchronous = OFF;

我还能做些什么?

如果我在Firefox SQLite Manager插件中运行相同的脚本,它会立即运行。

我运行了探查器。

所有时间都在

27seg System.Data.SQLite.SQLite3.Prepare(SQLiteConnection, String, SQLiteStatement, UInt32, String&)

此方法调用三种方法

12seg System.Data.SQLite.SQLiteConvert.UTF8ToString(IntPtr, Int32)
9seg System.Data.SQLite.SQLiteConvert.ToUTF8(String)
4seg System.Data.SQLite.UnsafeNativeMethods.sqlite3_prepare_interop(IntPtr, IntPtr, Int32, IntPtr&, IntPtr&, Int32&)

您要求显示插入内容。这里:

INSERT INTO [Criterio] ([cd1],[cd2],[cd3],[dc4],[dc5],[dt6],[dc7],[dt8],[dt9],[dt10],[dt11])VALUES('FFFFFFFF-FFFF-FFFF-FFFF-B897A4DE6949',10,20,'',NULL,NULL,'',NULL,julianday('2011-11-25 17:00:00'),NULL,NULL);

表:

CREATE TABLE Criterio (
   cd1          integer NOT NULL,
   cd2         text NOT NULL,
   dc3        text NOT NULL,
   cd4    integer NOT NULL,
   dt5           DATE NOT NULL DEFAULT CURRENT_TIMESTAMP,
   dt6         DATE NULL,
   dt7          DATE NULL,
   dc8   TEXT NULL,
   dt9   datetime NULL,
   dc10            TEXT NULL,
   dt11            datetime NULL,
   PRIMARY KEY (cd2 ASC, cd1 ASC)

);

C#代码:

        scriptSql = System.IO.File.ReadAllText(@"C:\Users\Me\Desktop\ScriptToTest.txt");

        using (DbCommand comando = Banco.GetSqlStringCommand(scriptSql))
        {
            try
            {
                using (TransactionScope transacao = new TransactionScope())
                {
                    Banco.ExecuteNonQuery(comando);
                    transacao.Complete();
                }
            }
            catch (Exception ex)
            {
                Logging.ErroBanco(comando, ex);
                throw;
            }
        }

2 个答案:

答案 0 :(得分:3)

我不知道为什么pst删除了他的答案,所以我会重新发布相同的信息,因为这似乎是正确答案。

根据SQLite常见问题解答 - INSERT is really slow - I can only do few dozen INSERTs per second

  

实际上,SQLite很容易在普通台式计算机上每秒执行50,000或更多INSERT语句。但它每秒只会进行几十次交易

     

...

     

默认情况下,每个INSERT语句都是自己的事务。但是如果用BEGIN ... COMMIT包围多个INSERT语句,则所有插入都被分组到一个事务中。

所以基本上你需要将INSERT分组为更少的事务。

更新:所以问题可能主要是由于SQL脚本的庞大规模 - SQLite需要在整个脚本执行之前对其进行解析,但解析器的设计目的是解析小脚本不是大规模的!这就是您在SQLite3.Prepare方法中花费了大量时间的原因。

相反,您应该使用参数化查询并在C#代码的循环中插入记录,例如,如果您的文本文件中的数据是CSV格式,则可以使用以下内容:

using (TransactionScope txn = new TransactionScope())
{
    using (DbCommand cmd = Banco.GetSqlStringCommand(sql))
    {
        string line = null;
        while ((line = reader.ReadLine()) != null)
        {
            // Set the parameters for the command at this point based on the current line
            Banco.ExecuteNonQuery(cmd);
            txn.Complete();
        }
    }
}

答案 1 :(得分:0)

您是否尝试过参数化插入?根据我的经验,交易会提高速度,但参数化查询会产生更大的影响。