【问题标题】:Dynamic SQL running way too longer动态 SQL 运行时间过长
【发布时间】:2016-12-01 22:54:06
【问题描述】:

我正在尝试运行一个应该加载超过 200M 记录的动态 SQL 查询。我试图一次加载所有记录,但得到了“System.OutOfMemory”异常,因此决定将时间间隔分成几个月。即使我只运行了一个月,以下运行了一个多小时。我对日期进行了硬编码,并在没有“While”的情况下运行它,它运行正常。有人可以检查并让我知道其中是否有错误。 以下是我的查询

DECLARE @FromDate VARCHAR(MAX)='',
        @params nvarchar(max) = N'@StartDate Date out,@EndDate Date out,@FromDate date out,@ToDate date out',
        @SQL NVARCHAR(MAX)=’’,
        @ToDate VARCHAR(MAX)='', 
        @StartDate VARCHAR(MAX)=’’,
        @EndDate VARCHAR(MAX)=’’;

SELECT  @FromDate= DATEADD(DAY,-365, GETUTCDATE()), @ToDate =     GETUTCDATE();
SELECT @StartDate=@FromDate, @EndDate=CAST(DATEADD(MONTH,1, @FromDate) AS DATE);
SET @SQL = '
WHILE ''' + @FromDate + ''' < ''' + @ToDate + '''
   BEGIN
   INSERT INTO dbo.Sales
   (
   ProductID,
   SaleDate,
   Quantity 
   )
 Select 
      ProductID,
      SaleDate,
      Quantity 
 from 
     OPENQUERY(TeraData1,''
        Select 
        PR_ID           AS   ProductID,
        SL_Date         AS   SaleDate,
        PR_QTY          AS   Quantity
    FROM
        Sales.Product
    where
SaleDate BETWEEN ' + @StartDate + 'AND '+ @EndDate + '
'')

SET  @FromDate =DATEADD(MONTH,1,'''+ @FromDate +''')
SET  @StartDate =DATEADD(MONTH,1,'''+ @StartDate +''')
SET  @EndDate =DATEADD(MONTH,1,'''+ @EndDate +''')
END’

 EXECUTE sp_executesql @SQL, @params,
                @FromDate=@FromDate,
                @ToDate=@ToDate,
                @StartDate = @StartDate out,
                @EndDate = @EndDate out;

【问题讨论】:

  • 为什么不使用存储过程/函数逻辑而不是动态SQL?
  • @TonyDong 有一点在您展示的语法中没有任何需要动态 sql 的内容,您可以使用常规的 WHILE 控制语法。尽管有点难以分辨,但问题可能是您在动态 sql 和控制流中混合了变量的范围
  • 你也在混合一些数据类型,这可能是问题的一部分

标签: sql sql-server tsql dynamic-sql


【解决方案1】:
DECLARE @FromDate DATE

SET @FromDate = DATEADD(YEAR,-1,GETUTCDATE())

WHILE @FromDate < GETUTCDATE()
BEGIN
   INSERT INTO dbo.Sales
   (
      ProductID,
      SaleDate,
      Quantity 
   )
 Select 
      ProductID,
      SaleDate,
      Quantity 
 from 
     OPENQUERY(TeraData1,
       Select 
          PR_ID           AS   ProductID,
          SL_Date         AS   SaleDate,
          PR_QTY          AS   Quantity
       FROM
          Sales.Product
       where
          SaleDate >= @FromDate AND SaleDate < DATEADD(MONTH,1,@FromDate)
    )

    SET  @FromDate =DATEADD(MONTH,1,@FromDate)
END

看起来你的变量/日期比你需要的多,而且你不需要动态 SQL,除非你想动态传递链接服务器名称或其他一些列。

还要为参数坚持使用适当的数据类型,而不是让 SQL 推断出你想要的值。

此外,您对日期使用 BETWEEN 会重复某些日期,因为它将包含在内,以修复比较的限制 1。

如果您确实想动态保持控制流在您的非动态 SQL 中并传递参数,这里是一个示例:

DECLARE @FromDate DATE

SET @FromDate = DATEADD(YEAR,-1,GETUTCDATE())

WHILE @FromDate < GETUTCDATE()
BEGIN

    DECLARE @LinkedServerName NVARCHAR(MAX) = 'TeraData1'
    DECLARE @ParamDef NVARCHAR(MAX) = '@FromDate DATE'
    DECLARE @SQL NVARCHAR(MAX)

    SET @SQL = '
      INSERT INTO dbo.Sales
      (
         ProductID,
         SaleDate,
         Quantity 
      )
    Select 
        ProductID,
        SaleDate,
        Quantity 
    from 
        OPENQUERY(' + @LinkedServerName + ',
          Select 
             PR_ID           AS   ProductID,
             SL_Date         AS   SaleDate,
             PR_QTY          AS   Quantity
          FROM
             Sales.Product
          where
             SaleDate >= @FromDate AND SaleDate < DATEADD(MONTH,1,@FromDate)
       )'

    EXECUTE sp_executesql @SQL, @PramDef, @FromDate = @FromDate

    SET  @FromDate =DATEADD(MONTH,1,@FromDate)
END

【讨论】:

    猜你喜欢
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 2018-04-07
    • 1970-01-01
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多