0

我有一组 30 个文件。我遍历这些文件,并为每个文件插入 1529 行,大约 30 列,219487 行,大约 6 列。

我在 C# 中执行此操作,并通过数据表插入(见底部)。对于 1529 行(30 列),我将插入分组为每批 1,300 行,对于 219,487 行(6 列),每批插入 50000 行。

插入每个批次时,没有多线程 - 一切都是顺序的(至少在我的代码中)。在我的代码行完成插入前一个文件之前,我不会从下一个文件开始。

考虑到这一点,我希望 SQL 服务器在恒定时间内完成每个文件(文件非常相似,总是插入 1529 和 219487)。

但是,每个文件的每个 SQL 插入所花费的时间线性增加 - 从第一个文件的 9 秒到第 30 个文件的 50 秒。我已将 CPU 时间与所用的 SQL 时间分开,一开始插入 6 列行之一需要 0.000033 秒。接近尾声,对于后面的文件,对于 6 列数据,所用时间为 0.000228。也就是说,插入219487行(6列)数据的时间增加了约7倍?

我将批量大小减少到 20000 并且没有任何区别。在过去,我相信我将其减少到 5000 和 10000,但仍然没有任何区别。我对底层 SQL 架构了解不多,所以我有点迷茫。

我觉得我正在超载 SQL 服务器。但是,是否给人的印象是这是按顺序完成的,而不是给 SQL 服务器分配作业?SQL 请求可能是通过线程产生的,但是我将批处理大小减少到 100(请参见下文),但这仍然没有帮助。完成的总时间更长,但每个文件仍然线性增加。

我已将批处理大小减少到 100(只是为了确保服务器不会超载)并且我仍然看到线性增加的时间?

在整个过程中,我一直指的是 SQL 插入所花费的时间,而不是每个文件的 SQL + CPU 时间的总和。

可能不可能确切地告知正在发生的事情,但我可以有一些提示和事情绝对避免以最好地解决这个问题吗?

我的 SQL 插入代码(每批插入调用)是:

private static void WriteResultsToDatabase(string tableName, DataTable tableToWrite)
        {

            using (SqlConnection connection =
                    new SqlConnection(connectionString))
            {
                SqlBulkCopy bulkCopy =
                    new SqlBulkCopy
                    (
                    connection,
                    SqlBulkCopyOptions.TableLock |
                    SqlBulkCopyOptions.FireTriggers |
                    SqlBulkCopyOptions.UseInternalTransaction,
                    null
                    );

                bulkCopy.DestinationTableName = tableName;
                for (int i = 0; i < tableToWrite.Columns.Count; i++)
                    bulkCopy.ColumnMappings.Add(tableToWrite.Columns[i].ColumnName, tableToWrite.Columns[i].ColumnName);
                try
                {
                    connection.Open();

                    bulkCopy.WriteToServer(tableToWrite);

                }
                finally
                {
                    connection.Close();
                }
            }
        }
4

2 回答 2

0

我觉得我正在超载 SQL 服务器

是的,这是一个很好的理由——尤其是并且仅当您的 sql 服务器在手机上运行或具有可悲的最终用户光盘时。否则 - 不。

我对底层 SQL 架构了解不多,所以我有点迷茫。

查出。获取查询计划。需要表 + 索引。独特的约束?是否存在没有索引的唯一约束?这会一直强制进行表扫描。

还值得:插入到您从原始表(微不足道)创建的临时表中,然后在一个语句中复制数据。

从第一个文件的 9 秒开始

对于 220.000 行,这已经足够了。我建议检查服务器在您的 poerations 期间有多忙以及表上的所有约束以匹配索引。和触发器;)

于 2012-05-02T11:33:14.933 回答
0

这可能是任何数量的事情,但对我来说显而易见的事情如下:

  1. 您在表上有一个聚集键,并且您没有按该键的顺序插入记录。对于每个插入操作,它都需要在完成任务之前对记录进行物理重新排序。
  2. 您有多个索引/外键对表进行检查,因此每次迭代您都会添加越来越多的信息以进行检查。
  3. 您的触发器没有被有效地使用,或者没有被有效地构造,以至于它需要针对整个表而不是最近插入的数据工作。
  4. 您已经设置了一个批量事务,但有些东西阻止了数据库服务器将其视为一个事务。确保活动监视器将此视为批量操作。
  5. 您正在按百分比而不是按固定数量自动增长数据库;对于每次增长,分配更多空间需要更长的时间。

这些都是我以前遇到过的问题;其中任何一种或任何组合都可能产生您所描述的症状。

于 2012-05-02T11:34:46.693 回答