我们有一个具有相当大记录数(10-2000 万行)的数据仓库,并且经常运行查询来计算特定日期之间的记录数,或者计算具有特定标志的记录数,例如
SELECT
f.IsFoo,
COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo
Run Code Online (Sandbox Code Playgroud)
性能并不差,但可能相对缓慢(在冷缓存上可能 10 秒)。
最近我发现我可以GROUP BY在索引视图中使用,因此尝试了类似于以下内容
CREATE VIEW TestView
WITH SCHEMABINDING
AS
SELECT
Date,
FlagId,
COUNT_BIG(*) AS WidgetCount
FROM Widgets
GROUP BY Date, FlagId;
GO
CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
Date,
FlagId
);
Run Code Online (Sandbox Code Playgroud)
因此,我的第一个查询的性能现在 < 100 毫秒,结果视图和索引 < 100k(尽管我们的行数很大,但日期和标志 ID 的范围意味着此视图仅包含 1000-2000 行)。
我认为这可能会降低对 Widget 表的写入性能,但没有 - 据我所知,向该表中插入和更新的性能几乎不受影响(另外,作为数据仓库,该表很少更新反正)
对我来说,这似乎好得令人难以置信——是吗?以这种方式使用索引视图时需要注意什么?
performance index sql-server materialized-view query-performance
在我们的应用程序中,我们有一个网格,用户可以在其中翻阅大量记录(10-2000 万)。网格支持在多列 (20+) 中按升序和降序排序。许多值也不是唯一的,因此应用程序还按 id 排序作为决胜局,以确保行始终出现在同一页面上。例如,如果用户想要按小部件大小(从最大的开始)排序,应用程序会生成一个看起来像这样的查询:
SELECT TOP 30
* -- (Pretend that there is a list of columns here)
FROM Test
-- WHERE widgetSize > 100
ORDER BY
widgetSize DESC,
id ASC
Run Code Online (Sandbox Code Playgroud)
此查询需要大约 15 秒才能运行(使用缓存数据),主要成本似乎是按小部件大小对大约 130 万行进行排序。在尝试调整此查询时,我发现如果我添加一个WHERE仅限于最大 widgetSizes的子句(在上面的查询中注释掉),则查询只需要约 800 毫秒(所有前 50,000 个结果的小部件大小都大于 100) .
为什么没有WHERE子句的查询速度会如此之慢?我检查了 widgetSize 列的统计数据,它们显示前 739 行的 WidgetSize > 506。由于只需要 30 行,SQL Server 可以不使用此信息来推断它只需要对具有小部件大小的行进行排序哪个大?

我知道我可以通过在和上添加索引来使这个特定查询更快地执行,但是这个索引只在这个特定场景中有用,并且如果(例如)用户反转排序方向就变得毫无价值。该表包含许多附加列,并且每个索引都很大(~200mb),因此我无法为每个可能的排序顺序添加索引。widgetSizeid
有什么方法可以让这些查询查询执行而不为每个可能的排序顺序添加索引?(用户可以按 20 多列中的任何一列进行排序)
以下脚本创建上表并用一些代表性数据填充它。该表比实际表窄得多,但仍然展示了我所看到的性能。在我的 PC 上,带有 where 子句的查询需要约 200 毫秒,而没有 where caluse 的查询需要约 800 …
如果我在 SQL 2005 Server 上备份数据库,然后将该备份还原到同一数据库服务器实例上的不同(新)数据库,则不会保留哪些内容(例如缓存的执行计划、统计信息等)。 .)