我正在编写一个脚本来填充一个非常简单的日期维度表,其粒度低至分钟级别。此表最终应包含代表smalldatetime
到1/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分钟才能完成。关于如何“调整”或改进此脚本的任何提示/建议?
此外,为了完整起见,fGetYearBegin
和fGetYearEnd
:
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
答案 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