【问题标题】:Indexing strategy on table表上的索引策略
【发布时间】:2010-09-30 01:51:58
【问题描述】:

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

EventID、EventTypeCode、EventStatusCode、EventDate

当前该表在主键“EventID”上有一个聚集索引,目前没有其他索引

EventTypeCode 和 EventStatusCode 列是 CHAR(3)(例如 'NEW'、'SEN'、'SAL')并且是外键

Common Selects 将是...

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 条记录,因为这是一个新应用程序
  • ...我或多或少只是想避免客户不得不在几年后打电话给我们抱怨应用程序变得“慢”,因为这张桌子会受到如此多的打击

【问题讨论】:

  • 编辑:Select 语句 where 子句还可以包含字段的组合,即 @fromdate 和 @todate AND EventTypeCode = @eventcode 之间的 EventDate 每天 300 次插入可能是保守的,可能更像500-800
  • 这完全改变了问题。

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


【解决方案1】:

我会在每个外键上建立一个索引(我通常为大多数外键建立索引),然后可能在日期字段上建立一个索引,具体取决于它在搜索中使用的频率。

【讨论】:

    【解决方案2】:

    策略一,提供可用于过滤的索引。表查找将获取剩余数据。这几乎使空间使用量增加了一倍,写入 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)
    

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

    如果 EventDate 在索引中排在第一位,则数据将按日期排序,然后每个日期将“待办事项”事件聚集在一起。 SQL Server 会在 12 月 1 日找到第一个待办事项,直到找到不符合条件的元素……然后在 12 月 2 日找到第一个待办事项,直到它没有待办事项……然后找到。 .. 持续 31 天。

    您想选择一个索引来放置您想要的项目彼此相邻。


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

    【讨论】:

      【解决方案3】:

      您对表格运行选择的频率如何?选择通常是正常处理的一部分还是更多用于报告和/或维护和调试?

      是否有初始数据加载?如果不是这样,那么表的大小就会非常小,并且可能会在未来几年保持这种状态。

      虽然您提供了一些示例选择,但您知道每种选择的运行频率吗?

      我可能会保留表原样并运行分析器以查看在生产中如何访问表。如果它是一个不断访问的表,并且可能成为不同功能的瓶颈,那么我最好猜测哪些列最常成为 WHERE 子句的一部分,并在其上放置一个索引。例如,如果有一个进程查看过去 24 小时内的所有事件,每 10 秒运行一次,那么日期列上的索引可能是有序的,我什至会聚集在那个索引上而不是主键上。

      【讨论】:

        猜你喜欢
        • 2013-07-25
        • 2012-12-22
        • 1970-01-01
        • 1970-01-01
        • 2018-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多