如何优化大表,以便仅针对最近数据的查询执行最佳?

Iva*_*anP 6 sql-server-2008 sql-server

所以我有一张不断增长的桌子。大多数查询只针对最近的数据,比如一个月前的数据。我想这是常见问题,但我不知道如何解决。

我愿意更改设计,或者 MsSql 中是否有解决此问题的机制。由于数据库正在生产中并且难以复制,因此我尝试不同解决方案的选择有限。

CREATE TABLE [dbo].[mydata](
[ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[Code] [varchar](20) NOT NULL,   -- index1 UNIQUE NONCLUSTERED INDEX
[Data2] [varchar](20) NULL,      
[Data3] [nvarchar](50) NOT NULL,
... bunch of DATA around 5kb
[Time_1] [datetime] NULL,    -- time created, -- index2 NONCLUSTERED INDEX
[Time_2] [datetime] NULL,    -- time finished ( usualy within few days ) -- index3 NONCLUSTERED INDEX
[Status] [int] NOT NULL,     -- active 
[Modid] [timestamp] NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 5

时间序列应按时间聚类:

CREATE TABLE [dbo].[mydata](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Code] [varchar](20) NOT NULL,   -- index1 UNIQUE NONCLUSTERED INDEX
[Data2] [varchar](20) NULL,      
[Data3] [nvarchar](50) NOT NULL,
... bunch of DATA around 5kb
[Time_1] [datetime] NULL,    -- time created, 
[Time_2] [datetime] NULL,    -- time finished ( usualy within few days ) -- index3 NONCLUSTERED INDEX
[Status] [int] NOT NULL,     -- active 
[Modid] [timestamp] NOT NULL,
CONSTRAINT NONCLUSTERED PRIMARY KEY ([ID])
);

CREATE CLUSTERED INDEX cdxMyDataTime_1 on dbi.mydata (Time_1);
Run Code Online (Sandbox Code Playgroud)

在时间序列数据中,时间几乎总是在查询中指定,通常作为一个范围。使用基于时间范围的聚集键查询将仅扫描表的相关部分。

ID 可以继续为逻辑主键角色提供服务,但是通过它对表进行集群几乎没有什么好处,因为 ID 从不用作范围。所以关闭它进入非聚集约束。基于 ID 的单例查找需要两次读取,但谁在乎,是两次快速读取。

如果您不能将 Time_1 作为聚集键,则经常使用的技巧是检索每天的 ID 范围,例如。创建天数和 min_ID/max_ID 表。然后使用覆盖您感兴趣的时间范围的 ID 范围来限制表上的扫描范围。这种方法的优点是它适用于多个时间列(您不能按 Time_1Time_2 进行聚类...)并且它的侵入性较小(可以在不修改表的情况下立即试用)。但是这种方法在应用程序查询设计中是非常具有侵入性的,它需要遵守纪律,记住在所需的日子里使用 ID 范围。请注意,由于 ID 通常不会更改,因此可以将它们缓存在应用程序中。

Time_1 和 Time_2 上的简单索引不起作用,因为它们达到了索引临界点。Time_1 和 Time_2 上的覆盖索引(包含 INCLUDE 列)会扩大数据大小,因为所需的包含列通常是...所有列。