sql - 表上的索引策略

标签 sql sql-server sql-server-2005 indexing

我有一个名为“EventTable”的 SQL Server 2005 表,定义如下:

事件ID、事件类型代码、事件状态代码、事件日期

当前表在主键“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 个事件的速度增长。

<小时/>

执行以下查询也很常见

where EventDate between '2008-12-01' and '2008-12-31'
  and EventTypeCode = 'todo'

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

最佳答案

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

on EventTable(EventDate)
on EventTable(EventTypeCode)
on EventTable(EventStatusCode)

策略2,提供可用于过滤的覆盖索引。不会有任何查找。 这会使空间使用和写入 IO 成本增加四倍。

on EventTable(EventDate, EventId,
              EventTypeCode, EventStatusCode)
on EventTable(EventTypeCode, EventId,
              EventDate, EventStatusCode)
on EventTable(EventStatusCode, EventId,
              EventDate, EventTypeCode)
<小时/>

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

由于您没有任何对多列进行筛选的查询,因此(在您的情况下)第一列之后的列顺序没有任何意义。

如果您有以下疑问

where EventDate = @EventDate
  and EventTypeCode = @EventTypeCode

那么这个覆盖索引就很有用了。 EventDate 可能比 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)

这会将所有“待办事项”事件放在一起,并按事件日期排序作为决胜局。 SQL Server 只需找到第一个元素并读取,直到找到不满足条件的元素并停止。

如果 EventDate 位于索引中的第一个,则数据将按日期排序,然后每个日期都会将“todo”事件聚集在一起。 SQL Server 将在 12-01 上找到第一个待办事项,读取直到找到不符合条件的元素...然后在 12-02 上找到第一个待办事项,读取直到它超出待办事项...然后查找。 .. 缺席 31 天。

您想要选择一个索引,使您想要的项目彼此相邻。

<小时/>

按照每天 300 条记录计算,您的表在 50 年内将达到 500 万条记录。这没那么大。任何一种策略都会奏效。策略 1 可能足够快(在空间方面犯错误)。

关于sql - 表上的索引策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/421002/

相关文章:

mysql - 从多列连接到一张表

sql - Oracle PL/SQL 字符串格式化

c# - 存储常用数据库表 ID 的最佳方法?

sql - 概念化 SQL 查询以获取不存在的数据

java - SQL异常 : Login failed for user ' ' JAVA

sql - 带有 IN 的多个表达式

sql - 检测 postgres 更新触发器中的列更改

sql - Postgres -> [22007] 错误 : invalid input syntax for type timestamp: ""

sql-server - 100k 行以随机顺序返回,请不要出现 SQL 超时

sql-server-2005 - SQL Server 2005 计算列被持久化