我有一个名为'EventTable'的SQL Server 2005表定义如下:
EventID,EventTypeCode,EventStatusCode,EventDate
目前该表在主键'EventID'上有一个聚簇索引,当前没有其他索引
EventTypeCode和EventStatusCode列是CHAR(3)(示例是'NEW','SEN','SAL')并且是外键
常见选择将是......
select * from EventTable Where EventDate = @dateparam; select * from EventTable Where EventTypeCode = @eventtype; select * from EventTable Where EventStatusCode = @statustype;
您将使用什么索引策略来处理上面的Select语句?
在3列上有覆盖(复合)指数是否更好?如果是这样,复合指数应该采用什么顺序?
或者3列中的每一列都有单独的索引?
该表将以每天约300个事件的速度增长.
执行诸如的查询也很常见
该表更有可能以每天500-800 /条的速度增长而不是300条 在正常使用ASP.NET应用程序期间,初始问题中提到的查询将在一天中运行多次 NHibernate'HQL'用于执行此类查询 没有初始加载的数据,该表现在只有大约10K记录,因为这是一个新的应用程序 ...我或多或少只是试图避免客户在几年内打电话给我们抱怨应用程序变得"慢",因为这个表会受到如此多的打击
Amy B..
6
策略1,提供可用于过滤的索引.表查找将获取剩余数据.这几乎使用空间和四倍写入IO成本加倍. 策略2,提供可用于过滤的覆盖索引.没有查找.这使空间的使用增加了四倍并且写入IO成本. 列顺序在覆盖索引(通常)中重要的原因是数据依次按每列排序.也就是说:第2列打破第1列.第3列打破第1列和第2列. 由于您没有任何过滤多列的查询,因此对第一列之后的列顺序没有意义(在您的情况下). 如果你有一个查询,如 然后这个覆盖指数将是有用的.EventDate可能比EventTypeCode更具选择性,因此它首先出现. 进一步编辑:如果您有查询,例如 那么这个指数最好: 这将把所有'todo'事件放在一起,由他们的EventDate命令作为打破平局.SQL Server只需找到第一个元素并读取,直到找到不符合条件的元素并停止. 如果EventDate是索引中的第一个,那么数据将按日期排序,然后每个日期将"todo"事件聚集在一起.SQL Server会在12-01上找到第一个todo,读取直到它找到一个不符合标准的元素...然后在12-02找到第一个待办事项,读取它直到todo的...然后找到. ..出去31天. 您想要选择一个索引,将您想要的项目放在一起. 每天300条记录,您的表将在50年内达到500万条记录.这不是那么大.这两种策略都可行.策略1可能足够快(错误在空间方面). 策略1,提供可用于过滤的索引.表查找将获取剩余数据.这几乎使用空间和四倍写入IO成本加倍. 策略2,提供可用于过滤的覆盖索引.没有查找.这使空间的使用增加了四倍并且写入IO成本. 列顺序在覆盖索引(通常)中重要的原因是数据依次按每列排序.也就是说:第2列打破第1列.第3列打破第1列和第2列. 由于您没有任何过滤多列的查询,因此对第一列之后的列顺序没有意义(在您的情况下). 如果你有一个查询,如 然后这个覆盖指数将是有用的.EventDate可能比EventTypeCode更具选择性,因此它首先出现. 进一步编辑:如果您有查询,例如 那么这个指数最好: 这将把所有'todo'事件放在一起,由他们的EventDate命令作为打破平局.SQL Server只需找到第一个元素并读取,直到找到不符合条件的元素并停止. 如果EventDate是索引中的第一个,那么数据将按日期排序,然后每个日期将"todo"事件聚集在一起.SQL Server会在12-01上找到第一个todo,读取直到它找到一个不符合标准的元素...然后在12-02找到第一个待办事项,读取它直到todo的...然后找到. ..出去31天. 您想要选择一个索引,将您想要的项目放在一起. 每天300条记录,您的表将在50年内达到500万条记录.这不是那么大.这两种策略都可行.策略1可能足够快(错误在空间方面).
where EventDate between '2008-12-01' and '2008-12-31'
and EventTypeCode = 'todo'
select * from EventTable Where EventDate = @dateparam;
select * from EventTable Where EventTypeCode = @eventtype;
select * from EventTable Where EventStatusCode = @statustype;
on EventTable(EventDate)
on EventTable(EventTypeCode)
on EventTable(EventStatusCode)
on EventTable(EventDate, EventId,
EventTypeCode, EventStatusCode)
on EventTable(EventTypeCode, EventId,
EventDate, EventStatusCode)
on EventTable(EventStatusCode, EventId,
EventDate, EventTypeCode)
where EventDate = @EventDate
and EventTypeCode = @EventTypeCode
on EventTable(EventDate, EventTypeCode,
EventId, EventStatusCode)
where EventDate between '2008-12-01' and '2008-12-31'
and EventTypeCode = 'todo'
on EventTable(EventTypeCode, EventDate,
EventId, EventStatusCode)
1> Amy B..:on EventTable(EventDate)
on EventTable(EventTypeCode)
on EventTable(EventStatusCode)
on EventTable(EventDate, EventId,
EventTypeCode, EventStatusCode)
on EventTable(EventTypeCode, EventId,
EventDate, EventStatusCode)
on EventTable(EventStatusCode, EventId,
EventDate, EventTypeCode)
where EventDate = @EventDate
and EventTypeCode = @EventTypeCode
on EventTable(EventDate, EventTypeCode,
EventId, EventStatusCode)
where EventDate between '2008-12-01' and '2008-12-31'
and EventTypeCode = 'todo'
on EventTable(EventTypeCode, EventDate,
EventId, EventStatusCode)