数据插入需要更长时间才能执行更多迭代

时间:2014-09-18 13:31:31

标签: c# sql visual-studio-2012 sql-server-ce-4

我有一个空的数据库,其中包含旧的旧数据库的迁移形式。

我将所有旧数据读入DataTables,工作正常。

有一个主表包含几乎每个表的链接,因此这是循环的。对于需要进入主表的每个记录,大约有7组表,每个表都只是依赖于彼此工作的表。因此,例如,订单表与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

1 个答案:

答案 0 :(得分:0)

您应该考虑查看目标表上的聚簇索引。它应该是小的(理想的和整数的)升序的,并且是唯一的。如果您正在为聚簇索引或guid使用业务密钥,那么您将面临页面拆分的风险,这会导致负载随时间变慢。

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

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