【发布时间】:2011-01-26 01:45:36
【问题描述】:
假设我有一个很长的表(约 3500 万行),名为 TimeCard,只有 5 列(tableID、CompanyID、UserID、ProjectID、DailyHoursWorked、entryDate)。这是一个非常简单的表格,记录了每个公司每个项目每天的员工工作时间。
我现在需要生成一份报告,以了解任何给定公司每个项目的员工每月的总工作时间。我不想在报表运行时执行所需的聚合,而是想构建一个类似表格的数据结构,其中已经包含按月聚合的所有公司/项目/用户数据,因此当报表运行时,我可以直接查询该数据结构无需执行任何运行时聚合,因为大约 3500 万条记录可能需要几分钟。
所以我有两种不同的方法。一个人创建了一个额外的物理表(CompanyID、UserID、ProjectID、MonthlyHoursWorked、Month)作为我的列,然后在 TimeCard 表中使用触发器来修改额外表中的值。或者我可以创建一个索引视图。所以我两个都试了。我首先使用以下代码尝试了索引视图:
CREATE VIEW [dbo].[vw_myView] WITH SCHEMABINDING AS
SELECT
JobID,
ProjectID,
Sum(DailyHoursWorked) AS MonthTotal,
DATEADD( Month, DATEDIFF( Month, 0, entryDate), 0 ) AS entryMonth,
CompanyID,
COUNT_BIG(*) AS Counter
FROM
dbo.TimeCard
Group By DATEADD( Month, DATEDIFF( Month, 0, entryDate ), 0 ), JobID, ProjectID, CompanyID
Go
CREATE UNIQUE CLUSTERED INDEX [IX_someIndex] ON [dbo].[vw_myView]
(
[CompanyID] ASC,
[entryMonth] ASC,
[UserID] ASC,
[ProjectID] ASC
)
正确创建的索引视图总共有大约 500 万行。
但是,如果我每次清除 SQL 缓存,并运行以下查询:*select * from vw_myView where companyID = 1*,大约需要 3 分钟。如果我使用上面提到的额外表路由,清除缓存,大约需要 4 秒。
我的问题是,索引视图对于这种特殊情况是不是一个糟糕的选择?特别是我很想知道每次更改基础表 (TimeCard) 或针对它运行查询时,是否会重新计算/重新聚合整个索引视图?
谢谢!
【问题讨论】:
-
您使用的是哪个版本的 SQL Server 2005?
-
在
entryMonth中不包含当月第一天的完整日期,您不能只将MONTH(entryDate)和可能的YEAR(entryDate)作为INT 吗?对我来说似乎容易多了(但话又说回来 - 我不知道你的确切要求)......
标签: sql sql-server sql-server-2005 indexed-view