表上的索引策略

use*_*212 4 sql sql-server indexing sql-server-2005

我有一个名为'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;
Run Code Online (Sandbox Code Playgroud)

您将使用什么索引策略来处理上面的Select语句?

在3列上有覆盖(复合)指数是否更好?如果是这样,复合指数应该采用什么顺序?

或者3列中的每一列都有单独的索引?

该表将以每天约300个事件的速度增长.


执行诸如的查询也很常见

where EventDate between '2008-12-01' and '2008-12-31'
  and EventTypeCode = 'todo'
Run Code Online (Sandbox Code Playgroud)
select * from EventTable Where EventDate = @dateparam;
select * from EventTable Where EventTypeCode = @eventtype;
select * from EventTable Where EventStatusCode = @statustype;
Run Code Online (Sandbox Code Playgroud)

  • 该表更有可能以每天500-800 /条的速度增长而不是300条
  • 在正常使用ASP.NET应用程序期间,初始问题中提到的查询将在一天中运行多次
  • NHibernate'HQL'用于执行此类查询
  • 没有初始加载的数据,该表现在只有大约10K记录,因为这是一个新的应用程序
  • ...我或多或少只是试图避免客户在几年内打电话给我们抱怨应用程序变得"慢",因为这个表会受到如此多的打击

Amy*_*y B 6

策略1,提供可用于过滤的索引.表查找将获取剩余数据.这几乎使用空间和四倍写入IO成本加倍.

on EventTable(EventDate)
on EventTable(EventTypeCode)
on EventTable(EventStatusCode)
Run Code Online (Sandbox Code Playgroud)

策略2,提供可用于过滤的覆盖索引.没有查找.这使空间的使用增加了四倍并且写入IO成本.

on EventTable(EventDate, EventId,
              EventTypeCode, EventStatusCode)
on EventTable(EventTypeCode, EventId,
              EventDate, EventStatusCode)
on EventTable(EventStatusCode, EventId,
              EventDate, EventTypeCode)
Run Code Online (Sandbox Code Playgroud)

列顺序在覆盖索引(通常)中重要的原因是数据依次按每列排序.也就是说:第2列打破第1列.第3列打破第1列和第2列.

由于您没有任何过滤多列的查询,因此对第一列之后的列顺序没有意义(在您的情况下).

如果你有一个查询,如

where EventDate = @EventDate
  and EventTypeCode = @EventTypeCode
Run Code Online (Sandbox Code Playgroud)

然后这个覆盖指数将是有用的.EventDate可能比EventTypeCode更具选择性,因此它首先出现.

on EventTable(EventDate, EventTypeCode,
              EventId, EventStatusCode)
Run Code Online (Sandbox Code Playgroud)

进一步编辑:如果您有查询,例如

where EventDate between '2008-12-01' and '2008-12-31'
  and EventTypeCode = 'todo'
Run Code Online (Sandbox Code Playgroud)

那么这个指数最好:

on EventTable(EventTypeCode, EventDate,
              EventId, EventStatusCode)
Run Code Online (Sandbox Code Playgroud)

这将把所有'todo'事件放在一起,由他们的EventDate命令作为打破平局.SQL Server只需找到第一个元素并读取,直到找到不符合条件的元素并停止.

如果EventDate是索引中的第一个,那么数据将按日期排序,然后每个日期将"todo"事件聚集在一起.SQL Server会在12-01上找到第一个todo,读取直到它找到一个不符合标准的元素...然后在12-02找到第一个待办事项,读取它直到todo的...然后找到. ..出去31天.

您想要选择一个索引,将您想要的项目放在一起.


每天300条记录,您的表将在50年内达到500万条记录.这不是那么大.这两种策略都可行.策略1可能足够快(错误在空间方面).