在表格中,我有一个Date
列,我希望按月和年分组。
我创建了两列:DateMonth
和DateYear
,我已用相应的月份和年份填充它们:
UPDATE t SET DateMonth = DATEPART(month, Date), DateYear = DATEPART(year, Date)
这样groupby查询就不会使用DATEPART()
(sql函数无法利用索引)。
groupby查询如下:
SELECT DateMonth, DateYear, COUNT(*) AS RowsCount FROM t GROUP BY DateMonth, DateYear
根据这些信息,什么类型的索引可以为以前的groupby查询提供更好的性能?
每列索引:
CREATE INDEX IX_DateMonth ON t(DateMonth)
CREATE INDEX IX_DateYear ON t(DateYear)
或一个涵盖两列的索引:
CREATE INDEX IX_DateMonth_DateYear ON t(DateMonth, DateYear)
答案 0 :(得分:3)
他们说最好的方法就是实际做到这一点:)
创建了一个包含100,000行的表。
CREATE TABLE DateTable (DateColumn DATETIME , DateMonth INT , DateYear INT)
GO
declare @FromDate date = '1970-01-01'
declare @ToDate date = '2015-12-31'
INSERT INTO DateTable(DateColumn)
select TOP 100000 dateadd(day, rand(checksum(newid())) *
(1+datediff(day, @FromDate, @ToDate)),@FromDate)
FROM master..spt_values v cross join master..spt_values v2
GO
UPDATE DateTable
set DateMonth = MONTH(DateColumn)
,DateYear = YEAR(DateColumn)
GO
<强>查询强>
使用两列上的单个索引和两列上的两个单独索引执行以下查询。
SELECT DateMonth,DateYear,COUNT(*)AS RowsCount 来自DateTable GROUP BY DateMonth,DateYear
两个单独的索引
CREATE INDEX IX_DateMonth ON DateTable(DateMonth)
GO
CREATE INDEX IX_DateYear ON DateTable(DateYear)
GO
具有两个单独索引的执行计划
一个综合指数
CREATE INDEX IX_DateMonth_DateYear7
ON DateTable(DateMonth, DateYear)
GO
具有不同索引的两个表
最后,我创建了两个表,DateTable在两列上都有两个独立的索引,DateTable2在两列上有一个复合索引,并比较了执行计划:
故事的道德
坚持一个复合索引,因为您按两列进行分组,复合索引将导致非群集索引扫描,这将比您在两列上有两个单独索引时获得的表扫描更便宜。