旋转表和慢查询性能

时间:2011-11-19 10:02:14

标签: sql-server

我在SQL Server 2005上遇到了一个非常棘手的性能问题。

设计可追溯到一点,应用程序正在处理的数据量已经增长了很多。现在它是无法忍受的缓慢,我需要以某种方式重构它。

我希望有人可以通过最佳实践来启发我。我做了一些研究和实验,导致了几个问题,我希望将它们放在一个帖子中并不是太糟糕的行为。

有问题的表具有以下结构(某些字段名称被混淆):

CREATE TABLE [Items] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [F1] [varchar](100) NOT NULL,
    [F2] [int] NOT NULL,
    [F3] [int] NULL,
    [amount] [float] NOT NULL,
    [F3] [nvarchar](250) NULL,
    [valid_from] [datetime] NOT NULL,
    [valid_until] [datetime] NOT NULL,
    [F4] [int] NOT NULL,
    [F5] [int] NULL,
    [F6] [bit] NULL DEFAULT ('false'),
    [F7] [datetime] NULL,
    [F8] [int] NULL,
    [F9] [int] NULL,
    [F9] [int] NOT NULL,
    CONSTRAINT [pk_pnl_korrekturen] PRIMARY KEY CLUSTERED ( [ID] )
)

此表中的记录表示对一天或一系列日期有效的货币金额。范围由valid_from和valid_until列给出。这些只包含日期,时间部分始终为00:00:00。

对于我们处理的每一天,我们在此表中添加大约一百万条记录,其中包含valid_from = valid_until。有一小组记录,范围> 1天。很小,只有约0.03%。

只要我们处理完日数据或需要重新处理数据,就会删除1天的项目。多日项目的寿命更长,通常为一年左右。

毫不奇怪,此表上的大多数查询都是从选择日期范围开始,然后是更多标准:

SELECT *
FROM Items
WHERE (valid_from <= @SomeDate) AND (valid_until >= @SomeDate)
   AND (F1 = @SomeValue) 

该表具有valid_from和valid_until的单独索引。但是,对于像这样的范围查询,这当然没有多大帮助。

因此,该表上的查询将运行Minutes。因为它们经常使应用程序几乎无法使用。

Q1:旋转表是否有最佳做法,每个&#34;章节&#34;每章只存在一段时间,然后被删除?我需要在这张桌子上进行一些额外的维护吗?

Q2:关于维护。上面的最终结构是通过一系列ALTER TABLE得出的。我不知道SQL-Server如何处理这些。我是否需要&#34;重建&#34;在某个时候有桌子?

问题3:我尝试创建一个索引,帮助SQL-Server利用大多数记录仅在特定日期有效的事实。我在其上添加了一个计算字段和索引:

ALTER TABLE Items
ADD SingleDay AS (CASE WHEN (valid_from=valid_until) THEN 1 ELSE 0 END) PERSISTED

CREATE NONCLUSTERED INDEX IX_proc_pnl_items_valid_from_SingleDay 
ON Items (valid_from, SingleDay)

然后查询:

WHERE ((SingleDay = 1) AND (valid_from = @SomeDate))
   OR ((SingleDay = 0) AND (valid_from <= @SomeDate) AND (valid_until >= @SomeDate))

我查看了这个查询计划,它确实使用了我的新索引。然而,如果我只做一个人数,它只会更快。在我选择实际数据的那一刻,我没有得到任何改进。那就是:

SELECT COUNT(*) FROM Items 
WHERE (valid_from <= @SomeDate) AND (valid_until >= @SomeDate)

运行约一分钟。

SELECT COUNT(*) FROM Items 
WHERE ((SingleDay = 1) AND (valid_from = @SomeDate))
   OR ((SingleDay = 0) AND (valid_from <= @SomeDate) AND (valid_until >= @SomeDate))

几乎立即返回。

但是

SELECT ID FROM Items 
WHERE (valid_from <= @SomeDate) AND (valid_until >= @SomeDate)

SELECT ID FROM Items 
WHERE ((SingleDay = 1) AND (valid_from = @SomeDate))
   OR ((SingleDay = 0) AND (valid_from <= @SomeDate) AND (valid_until >= @SomeDate))

两者都需要一分钟。

有人可以向我解释一下,或者就如何调查问题给我一些建议吗?

1 个答案:

答案 0 :(得分:0)

尝试使用“having”而不是