Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 表的索引策略_Sql_Sql Server_Sql Server 2005_Indexing - Fatal编程技术网

Sql 表的索引策略

Sql 表的索引策略,sql,sql-server,sql-server-2005,indexing,Sql,Sql Server,Sql Server 2005,Indexing,我有一个名为“EventTable”的SQL Server 2005表,定义如下: EventID、EventTypeCode、EventStatusCode、EventDate 当前该表在主键“EventID”上有聚集索引,当前没有其他索引 EventTypeCode和EventStatusCode列是CHAR(3)(示例为“NEW”、“SEN”、“SAL”),是外键 共同选择将是 select * from EventTable Where EventDate = @dateparam; s

我有一个名为“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个事件的速度增长


执行查询也很常见,例如

其中,事件日期介于“2008-12-01”和“2008-12-31”之间
和EventTypeCode='todo'

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

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

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

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)
策略2,提供可用于筛选的覆盖索引。不会有任何查询。 这使空间使用和写入IO成本增加了四倍

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)

列顺序在覆盖索引中起重要作用的原因(通常)是数据按每列顺序依次排列。也就是说:第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找到第一个todo,读取直到找到不符合条件的元素。。。然后在12-02找到第一个待办事项,阅读直到它超出待办事项的范围。。。然后找到。。。他在外面呆了31天

您需要选择一个索引,该索引将要放置的项彼此相邻



以每天300条记录的速度,您的表将在50年内达到500万条记录。这没那么大。这两种策略都会奏效。策略1可能足够快(在空间方面出错)。

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

是否有初始数据负载?如果不是的话,桌子的大小是相当小的,并且可能在未来几年保持这种状态

虽然您给出了一些示例选择,但您知道每种类型的选择运行的频率吗


我可能会让表保持原样,运行profiler来查看在生产中如何访问该表。如果它将是一个不断被访问的表,并且可能成为不同函数的瓶颈,那么我将最好地猜测哪些列最频繁地成为WHERE子句的一部分,并在其上放置一个索引。例如,如果有一个进程查看过去24小时内每10秒运行一次的所有事件,那么date列上的索引可能是有序的,我甚至会在该列上进行聚类,而不是主键。

EDIT:Select语句where子句还可以包括字段的组合,也就是说,如果EventDate介于@fromdate和@todate之间,EventTypeCode=@eventcode每天插入300次可能是保守的,那么可能更像是500-800次,这完全改变了问题。