我有一个具有以下结构的SQL数据表:
CREATE TABLE Data(
Id uniqueidentifier NOT NULL,
Date datetime NOT NULL,
Value decimal(20, 10) NULL,
RV timestamp NOT NULL,
CONSTRAINT PK_Data PRIMARY KEY CLUSTERED (Id, Date)
)
不同的Id的数量在3000到50000之间。
表的大小变化到十亿行以上。
一个ID最多可以覆盖表格的5%至几行。
此表上最常执行的查询是:
SELECT Id, Date, Value, RV
FROM Data
WHERE Id = @Id
AND Date Between @StartDate AND @StopDate
我现在必须在ID的一个子集上实现增量数据检索,包括更新。
然后,我使用了一个请求方案,在该方案中,调用者提供了特定的行版本,检索数据块,并将返回数据的最大行版本值用于后续调用。
我已经写了这个程序:
CREATE TYPE guid_list_tbltype AS TABLE (Id uniqueidentifier not null primary key)
CREATE PROCEDURE GetData
@Ids guid_list_tbltype READONLY,
@Cursor rowversion,
@MaxRows int
AS
BEGIN
SELECT A.*
FROM (
SELECT
Data.Id,
Date,
Value,
RV,
ROW_NUMBER() OVER (ORDER BY RV) AS RN
FROM Data
inner join (SELECT Id FROM @Ids) Ids ON Ids.Id = Data.Id
WHERE RV > @Cursor
) A
WHERE RN <= @MaxRows
END
当@MaxRows
将范围取决于如何分块的客户会希望他的数据500,000到200万之间。
我尝试了不同的方法:
- 在(Id,RV)上建立索引:
CREATE NONCLUSTERED INDEX IDX_IDRV ON Data(Id, RV) INCLUDE(Date, Value);
使用索引,查询征求行,其中RV = @Cursor
每个Id
中@Ids
,阅读下面的行然后合并的结果和排序。
效率取决于@Cursor
价值的相对位置。
如果它接近数据的末尾(按RV排序),则查询是瞬时的,如果不是,则查询可能要花费几分钟(永远不要让它运行到末尾)。
这种方法的问题是,@Cursor
要么接近数据的末尾,而且排序并不麻烦(如果查询返回的行少于,甚至不需要@MaxRows
),要么排序更晚,而且查询必须对@MaxRows * LEN(@Ids)
行进行排序。
- RV索引:
CREATE NONCLUSTERED INDEX IDX_RV ON Data(RV) INCLUDE(Id, Date, Value);
查询使用索引来查找该行,RV = @Cursor
然后在其中读取每一行,并丢弃未请求的ID直到到达@MaxRows
。
效率则取决于所请求的Ids(LEN(@Ids) / COUNT(DISTINCT Id)
)的百分比及其分布。
请求的Id%越多意味着丢弃的行越少,这意味着读取效率越高;请求的ID%越少,意味着丢弃的行越多,对于相同数量的结果行,意味着更多的读取。
这种方法的问题在于,如果所请求的ID仅包含几个元素,则可能必须读取整个索引才能获得所需的行。
- 使用筛选索引或索引视图
CREATE NONCLUSTERED INDEX IDX_RVClient1 ON Data(Id, RV) INCLUDE(Date, Value)
WHERE Id IN (/* list of Ids for specific client*/);
要么
CREATE VIEW vDataClient1 WITH SCHEMABINDING
AS
SELECT
Id,
Date,
Value,
RV
FROM dbo.Data
WHERE Id IN (/* list of Ids for specific client*/)
CREATE UNIQUE CLUSTERED INDEX IDX_IDRV ON vDataClient1(Id, Rv);
这种方法可以实现非常有效的索引编制和查询执行计划,但有以下缺点:1.实际上,我将必须实现动态SQL以创建索引或视图,并修改请求过程以使用正确的索引或视图。2.我将必须维护现有客户端(包括存储)的一个索引或视图。3.每次客户必须修改其请求的ID列表时,我都必须删除索引或查看并重新创建它。
我似乎找不到适合我需求的方法。
我正在寻找更好的想法来实现增量数据检索。这些想法可能意味着重新构造请求方案或数据库模式,尽管如果有的话我更喜欢一种更好的索引方法。
Value
列。@crokusek:不会按RV排序,ID而不是RV只会增加排序工作量,而没有任何好处,我不理解您的评论背后的原因。根据我的阅读,RV应该是唯一的,除非将数据专门插入到该列中,而应用程序则不会。