动态SQL INSERT比它应该的时间长30倍

时间:2012-09-24 10:01:49

标签: c# sql-server-2008 dynamic-sql

我们构建了一个可用于创建数据仓库的C#.NET系统。该系统采用选定的数据库并针对这些数据库运行脚本以创建组合的数据库/仓库。

现在,我有三个数据库要编译成一个数据库,我从每个数据库中复制两个表(表[XI]和表[XII] - 它们具有一对多关系,但没有设置约束复制时间/ INSERT INTO)。要运行的脚本的数字和每个表的相关大小如下:

执行的脚本包含30个SQL查询。

  1. DatabaseA

    Table [XI]  29,026 Rows (size 20,128Kb).
    Table [XII] 531,958 Rows (size 50,168Kb).
    Time taken for entire script: 1.51s.
    
  2. DatabaseB

    Table [XI]  117,877 Rows (size 17,000Kb).
    Table [XII] 4,000,443 Rows (size 512,824Kb).
    Time taken for entire script: 2.04s.
    
  3. 这些都运行良好和快速。下一个几乎与第一个完全相同,但需要40倍的时间!

    1. DatabaseC

      Table [XI]  29,543 Rows (size 20,880Kb).
      Table [XII] 538,302 Rows (size 68,000Kb).
      Time taken for entire script: 44.38s.
      
    2. 我无法解释为什么这么长时间。我使用过SQL Server Profiler和性能监视器,但我无法确定性能发生这种巨大变化的原因。

      用于执行更新的查询是动态的,并显示在此问题的底部 - 由于显式引用了所需的列,因此查询很大。我的问题是;什么可能导致执行时间的过度增加?

      非常感谢任何线索。

      SQL:

      DECLARE @DbName NVARCHAR(128);
      SET @DbName = (SELECT TOP 1 [DbName] 
                     FROM [IPACostAdmin]..[TmpSpecialOptions]);
      DECLARE @FilterSql NVARCHAR(MAX);
      SET @FilterSql = (SELECT TOP 1 [AdditionalSQL] 
                        FROM [IPACostAdmin]..[TmpSpecialOptions]);
      DECLARE @SQL NVARCHAR(MAX);
      DECLARE @SQL1 NVARCHAR(MAX);
      DECLARE @SQL2 NVARCHAR(MAX);
      SET @SQL1 = 
          'INSERT INTO [' + @DbName + ']..[Episode] 
              ([Fields1], ..., [FieldN])'; 
      SET @SQL2 = 
      'SELECT 
           [Fields1], ..., [FieldN] 
      FROM [B1A] ' + @FilterSql + ';'; 
      SET @SQL = @SQL1 + @SQL2;
      EXEC(@SQL);
      GO
      

      注意:为了清楚起见,我将动态SQL拆分为@SQL1@SQL2。另请注意,由于空间原因,我没有显示所有列,而且这在很大程度上是多余的。

      EDIT1。

      1。数据库位于同一台服务器上。

      2。数据库文件(包括日志)位于同一驱动器上的同一目录中。

      3。在INSERT INTO时,源数据库(DatabaseA / B / C)或数据仓库数据库上没有设置主/外键或约束。

      EDIT2。我在管理工作室运行了上述查询,耗时5秒!?

      EDIT3。我添加了一个临时CLUSTERED INDEX,希望这有助于此查询,这也无济于事。

2 个答案:

答案 0 :(得分:1)

有些信息很难知道:

1:数据库在同一台服务器上?

2:对于A和C,db文件和日志文件在同一个驱动器上?

(一旦我遇到两个数据库的问题,其中一个在SSD驱动器上而另一个在HDD中。这是读取数据的问题)

3:关于碎片的DB统计数据? (表没有约束,但定义了索引?)

答案 1 :(得分:0)

这是由于在前一个DELETE查询有时间更新整个表之前运行CREATE CLUSTERED INDEX查询引起的。解决方案是使用BEGIN TRANSACTIONCOMMIT关键字。这迫使SQL Server在获取任何其他操作之前完成索引

请注意,只有在使用修改现有表单的动态SQL语句执行CREATE CLUSTERED INDEX查询时才会出现此问题。

我希望这有助于其他人。