我在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))
两者都需要一分钟。
有人可以向我解释一下,或者就如何调查问题给我一些建议吗?
答案 0 :(得分:0)
尝试使用“having”而不是