执行的迭代越多,数据插入的时间就越长

本文关键字:时间 插入 迭代 执行 数据 | 更新日期: 2023-09-27 18:22:26

我有一个空数据库,它将包含旧遗留数据库的迁移形式。

我把所有的旧数据读入DataTables,它运行良好。

有一个主表,它包含几乎每个表的链接,所以这是循环的。对于每个需要进入主表的记录,大约有7组表,其中每一组表都只是相互依赖才能工作的表。例如,Orders表与OrderLine表在同一组中,因为一个表依赖于另一个表。

由于这7个组中的每一个都可以在没有来自另一个组的任何信息的情况下完成,因此我为每个组使用不同的线程来启动迁移过程。

每种方法都只需运行遗留数据表中的相关记录,并对其进行消毒,然后将其插入到新数据库中。

我有一个数据访问类,它在类的生存期内保持SQLCeConnection对象的打开状态。

每次插入和读取操作都会碰到以下两种方法:

/// <summary>
/// Executes a single INSERT, UPDATE, DELETE or other Sql Command that modifies the schema or data of the database
/// </summary>
/// <param name="sql">The command to execute</param>
/// <param name="parameters">Any parameters in the command</param>
public void ExecuteCommand(string sql, SqlServerCeParameter[] parameters)
{
    //print debug statements if necessary
    if (_outputSqlStatementsToFile == true) PrintSqlDebuggingInformation(sql, parameters);
    //create the command that will execute the Sql
    using (var command = new SqlCeCommand(sql, _connection))
    {
        //add any parameters
        if (parameters != null) command.Parameters.AddRange(parameters.Select(p => p.ParameterBehind).ToArray());
        //open the connection 
        if (_connection.State == ConnectionState.Closed)
        {
            _connection.Open();
        }
        //execute the command
        command.ExecuteNonQuery();
    }
}
 /// <summary>
    /// Executes a query that returns a single value, for example a COUNT(*) query
    /// </summary>
    /// <typeparam name="T">The type of the value returned by the query, for example COUNT(*) would be an Integer</typeparam>
    /// <param name="sql">The query to execute</param>
    /// <param name="parameters">Any parameters in the query</param>
    /// <returns>A single value cast to type T</returns>
    public T ExecuteQuery<T>(string sql, SqlServerCeParameter[] parameters)
    {
        //print debug statements if necessary
        if (_outputSqlStatementsToFile == true) PrintSqlDebuggingInformation(sql, parameters);
        //the result
        T result;
        //create the command that will execute the Sql
        using (var command = new SqlCeCommand(sql, _connection))
        {
            //add any parameters
            if (parameters != null) command.Parameters.AddRange(parameters.Select(p => p.ParameterBehind).ToArray());
            //open the connection 
            if (_connection.State == ConnectionState.Closed)
            {
                _connection.Open();
            }
            //execute the command
            var sqlResult = command.ExecuteScalar();
            //cast the result to the type given to the method
            result = (T)sqlResult;
        }
        //return the result
        return result;
    }

每次完成一个记录,即整个记录以及与该记录相关的所有内容都会被完全迁移。

我有一个秒表在运行,覆盖迭代的整个代码,这样我就可以计算每次迭代所花费的平均毫秒数。

在32000多行的开头,毫秒数在180-220毫秒之间,但随着时间的推移,这个数字稳步增加,直到每次迭代超过2秒。

每一项记录都略有不同,有些记录天生需要更长的时间才能完成,但我很确定不应该持续增加。我预计它会在迁移的早期大幅波动,然后稳定在一个相对一致的数字

我想知道这是否与SQLServerCe连接有关,也许你在不关闭它的情况下使用得越多,它就越慢?

  1. C#
  2. Visual Studio 2012
  3. SqlServerCe 4.0

执行的迭代越多,数据插入的时间就越长

您应该考虑查看目标表上的聚集索引。它应该是小的(理想情况下是整数,)升序,并且是唯一的。如果您正在为聚集索引或guid使用业务密钥,那么您将面临页面拆分的风险,这将随着时间的推移而减缓负载。

您还可以考虑删除任何外键约束或索引,然后在完成后重新添加它们。

这似乎与索引有关。确定这一点的一个简单测试是每隔10K迭代左右截断一次表。如果你不再看到速度减慢,那么很可能是由于插入单个记录的IO。