大家好

我希望有人可以帮助我改进必须定期运行的查询。目前执行需要40多分钟。在此期间,它使用了全部分配的内存,但 CPU 使用率大多在 2% - 5% 之间徘徊,时不时地跳跃到 40%,持续几秒钟。

我有这张表(简化示例):

    CREATE TABLE [dbo].[dataTable]
    (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [dteEffectiveDate] [date] NULL,
    [dtePrevious] [date] NULL,
    [dteNext] [date] NULL,
    [Age] [int] NULL,
    [Count] [int] NULL
    ) ON [PRIMARY]

    GO

以下是一些输入值:

INSERT INTO [YourDB].[dbo].[dataTable]
           ([dteEffectiveDate]
           ,[dtePrevious]
           ,[dteNext]
           ,[Age]
           ,[Count])
     VALUES
('2009-01-01',NULL,'2010-01-01',40,300),
('2010-01-01','2009-01-01', NULL,40,200),
('2009-01-01',NULL, '2010-01-01',20,100),
('2010-01-01','2009-01-01', NULL,20,50),
('2009-01-01',NULL,'2010-01-01',30,10)
GO

每个条目都有一个 dteEffectiveDate 字段。此外,每个都有一个 dtePrevious 和 dteNext,反映最近的上一个/下一个生效日期的日期。现在我想要的是一个查询,它将计算特定年龄内连续周期之间的计数字段的中值。

例如,在上面的数据中,对于 40 岁的人,我们在 2009 年 1 月 1 日有 300 名,在 2010 年 1 月 1 日有 200 名,因此查询应生成 250 名。

请注意,年龄 30 只有一项,即 10。这是2009年1月1日。2010/01/01 没有任何条目,但我们知道此时已捕获数据,因此没有任何条目意味着此时 30 为 0。因此查询应该产生 5。

为了实现这一点,我使用表本身的 FULL JOIN,并使用 ISNULL 来选择值。这是我的代码:

SELECT

    ISNULL(T1.dteEffectiveDate,T2.dtePrevious) as [Start Date]
    ,ISNULL(T1.dteNext,T2.dteEffectiveDate)  as [End Date]
    ,ISNULL(T1.Age,T2.Age) as Age 
    ,ISNULL(T1.[Count],0) as [Count Start]
    ,ISNULL(T2.[Count],0)   as [Count End]
    ,(ISNULL(T1.[Count],0)+ISNULL(T2.[Count],0))/2 as [Mid Count]

    FROM
    [ExpDBClient].[dbo].[dataTable] as T1
    FULL JOIN [ExpDBClient].[dbo].[dataTable] as T2

    ON 
    T2.dteEffectiveDate = T1.dteNext
    AND T2.Age = T1.Age

    WHERE ISNULL(T1.dteEffectiveDate,T2.dtePrevious) is not null
    AND ISNULL(T1.dteNext,T2.dteEffectiveDate) is not null

GO

其输出:

Start Date  End Date    Age Count Start Count End   Mid Lives
2009-01-01  2010-01-01  40  300         200         250
2009-01-01  2010-01-01  20  100         50          75
2009-01-01  2010-01-01  30  10          0           5

它工作得很好,但是当我在实际数据(大约 700 万条记录)上运行它时,执行时间非常长。

有没有人有什么建议?

谢谢
卡尔

有帮助吗?

解决方案

很难提出很多建议。

我肯定会推荐的一件事是在 JOIN 条件中用作外键的那些列上的索引,例如

  • Age
  • dteEffectiveDate
  • dteNext

分别在每个列上创建一个 NONCLUSTERED 索引并再次测量。如果只有几个数据行,则无法衡量任何改进 - 但如果有数百万行,则可能会产生影响。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top