SQL Server:填充(分钟)日期维度表

时间:2016-01-05 22:51:47

标签: sql sql-server data-warehouse sql-tuning

我正在编写一个脚本来填充一个非常简单的日期维度表,其粒度低至分钟级别。此表最终应包含代表smalldatetime1/1/2000每分钟的12/31/2015 23:59

以下是该表的定义:

CREATE TABLE [dbo].[REF_MinuteDimension] (
    [TimeStamp] SMALLDATETIME NOT NULL,
    CONSTRAINT [PK_REF_MinuteDimension] PRIMARY KEY CLUSTERED ([TimeStamp] ASC) WITH (FILLFACTOR = 100)
);

以下是该脚本的最新版本:

DECLARE @CurrentTimeStamp AS SMALLDATETIME;
SELECT TOP(1) @CurrentTimeStamp = MAX([TimeStamp]) FROM [dbo].[REF_MinuteDimension];

IF @CurrentTimeStamp IS NOT NULL
    SET @CurrentTimeStamp = DATEADD(MINUTE, 1, @CurrentTimeStamp);
ELSE
    SET @CurrentTimeStamp = '1/1/2000 00:00';

ALTER TABLE [dbo].[REF_MinuteDimension] DROP CONSTRAINT [PK_REF_MinuteDimension];

WHILE @CurrentTimeStamp < '12/31/2050 23:59'
BEGIN

    ;WITH DateIndex ([TimeStamp]) AS
    (
        SELECT @CurrentTimeStamp
        UNION ALL
        SELECT DATEADD(MINUTE, 1, [TimeStamp]) FROM DateIndex di WHERE di.[TimeStamp] < dbo.fGetYearEnd(@CurrentTimeStamp)
    )
    INSERT INTO [dbo].[REF_MinuteDimension] ([TimeStamp])
        SELECT di.[TimeStamp] FROM DateIndex di
    OPTION (MAXRECURSION 0);

    SET @CurrentTimeStamp = DATEADD(YEAR, 1, dbo.fGetYearBegin(@CurrentTimeStamp))

END

ALTER TABLE [dbo].[REF_MinuteDimension] ADD CONSTRAINT [PK_REF_MinuteDimension] PRIMARY KEY CLUSTERED ([TimeStamp] ASC) WITH (FILLFACTOR = 100);

有几点需要指出:

  • 我添加了逻辑删除,然后在表上重新添加主键约束,希望提高性能。
  • 我添加了逻辑,将INSERTS分成年度批次,以最大限度地减少对事务日志的影响。另外,我们正在使用SIMPLE恢复模型。

性能如此,大约需要15-20分钟才能完成。关于如何“调整”或改进此脚本的任何提示/建议?

此外,为了完整起见,fGetYearBeginfGetYearEnd

CREATE FUNCTION dbo.fGetYearBegin
(
    @dtConvertDate datetime
)
RETURNS smalldatetime
AS
BEGIN
    RETURN DATEADD(YEAR, DATEDIFF(YEAR, 0, @dtConvertDate), 0) 
END


CREATE FUNCTION dbo.fGetYearEnd
(
    @dtConvertDate datetime
)
RETURNS smalldatetime
AS
BEGIN
    RETURN DATEADD(MINUTE, -1, DATEADD(YEAR, 1, dbo.fGetYearBegin(@dtConvertDate)))
END

1 个答案:

答案 0 :(得分:2)

我的服务器需要11秒......

If      Object_ID('tempdb..#someNumbers') Is Not Null Drop Table #someNumbers;
Create  Table #someNumbers (id Int);

Declare @minutes Int,
        @days Int;

Select  @minutes = DateDiff(Minute,'1/1/2000 00:00','1/2/2000 00:00'),
        @days = DateDiff(Day,'1/1/2000 00:00','1/1/2051 00:00');

With    Base As
(       
        Select  1 As seedID
        Union   All
        Select  1
),      Build As
(
        Select  seedID
        From    Base
        Union   All
        Select  b.seedID + 1
        From    Build b
        Cross   Join Base b2
        Where   b.SeedID < 14
)
Insert  #someNumbers
Select  Row_Number() Over (Order By seedID) As id
From    Build
Option (MaxRecursion 0);

If      Object_ID('tempdb..#values') Is Not Null Drop Table #values;
Create  Table #values ([TimeStamp] SmallDateTime NOT NULL);

With    Dates As
(
        Select  DateAdd(Day,id-1,'1/1/2000 00:00') As [TimeStamp]
        From    #someNumbers
        Where   id <= @days
)
Insert  #values
Select  Convert(SmallDateTime,DateAdd(Minute,id-1,[TimeStamp]))
From    Dates d
Join    #someNumbers sn
        On  sn.id <= @minutes
Order   By 1