假设我有一张桌子
CREATE TABLE Ticket (
TicketId int NOT NULL,
InsertDateTime datetime NOT NULL,
SiteId int NOT NULL,
StatusId tinyint NOT NULL,
AssignedId int NULL,
ReportedById int NOT NULL,
CategoryId int NULL
);
Run Code Online (Sandbox Code Playgroud)
在这个例子中TicketId
是主键。
我希望用户能够针对该表创建“部分临时”查询。我说部分是因为查询的一些部分将始终固定:
InsertDateTime
ORDER BY InsertDateTime DESC
用户可以选择过滤任何其他列。他们可以过滤无、一个或多个。对于每一列,用户可以从一组值中进行选择,这些值将作为析取应用。例如:
SELECT
TicketId
FROM (
SELECT
TicketId,
ROW_NUMBER() OVER(ORDER BY InsertDateTime DESC) as RowNum
FROM Ticket
WHERE InsertDateTime >= '2013-01-01' AND InsertDateTime < '2013-02-01'
AND StatusId IN (1,2,3)
AND (CategoryId IN (10,11) OR CategoryId IS NULL)
) _
WHERE RowNum BETWEEN 1 AND 100;
Run Code Online (Sandbox Code Playgroud)
现在假设该表有 100,000,000 行。
我能想到的最好的方法是包含每个“可选”列的覆盖索引:
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Run Code Online (Sandbox Code Playgroud)
这给了我一个查询计划如下:
看起来还不错。大约 80%-90% 的成本来自 Index Seek 操作,这是理想的。
是否有更好的策略来实现这种搜索?
我不一定要将可选过滤卸载到客户端,因为在某些情况下,“固定”部分的结果集可能是 100 或 1000。然后,客户端还将负责排序和分页,这对客户端来说可能太多了。
如果此特定工作负载是针对表的大部分查询,您可能会考虑:
ALTER TABLE Ticket ADD CONSTRAINT PK_Ticket PRIMARY KEY NONCLUSTERED (TicketId);
CREATE UNIQUE CLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime ASC
);
Run Code Online (Sandbox Code Playgroud)
注意事项:
优点:
归档时间: |
|
查看次数: |
2055 次 |
最近记录: |