RID 与 INCLUDE 在大范围内

gre*_*reg 7 sql-server

我有一张存放笔记的桌子

create tblNote(  
  Id int identity(1,1),  
  ParentId  int ,   
  ParentType varchar(32),   
  NoteType varchar(32),   
  Note varchar(max),  
  CreatedBy varchar(25),   
  CreatedDate  datetime,   
  .  
  .  
  .  
  <other metadata about the note>  
)  
Run Code Online (Sandbox Code Playgroud)

我最近阅读了很多关于 MSSS 如何处理索引(2005 年及以后)的文章。

我在 ID 上有一个聚集索引

[我已经考虑将聚集索引更改为 parentId、parentType,因为它相当狭窄并且是静态的。]

针对该表的绝大多数查询将遵循

select NOTE, createdDate, createdBy 
from tblNote 
where parentId = 12 and parentType = 'RFQ'
Run Code Online (Sandbox Code Playgroud)

我今天想问的问题(尽管欢迎任何反馈)是这样的:

我可以添加的 NC 索引是:

create index  idx_nc_note_parent(  
        parentId ,   
        parenttype  
    )  
    include (createdby, createdDate)  
Run Code Online (Sandbox Code Playgroud)

这对于创建小笔记列表很有用,我们可能会在其中包含谁和何时键入信息。

我很犹豫要不要包括一个varchar(max)领域。看起来它真的会伤害将被缓存的索引量(这是合理的还是不合理的)

假设我不包含该NOTE字段,则需要 RID 查找才能在需要时实际获取笔记内容。

虽然我已经阅读了很多关于 RID 查找有多昂贵的信息,但与进行表扫描相比,拥有此索引仍然必须更好,对吗?

[为代码块道歉,我添加了 4 个空格,但也许我做错了?]

Jon*_*gel 5

由于您说大多数查询通常会返回几行,因此让查询使用 RID 查找(在本例中为键查找,因为表具有聚集索引)非常适合检索潜在的大字段。对于高度可用的系统,我不建议在索引中放置 LOB 类型,因为这会阻止在线重建(对于 2012 之前的 SQL Server 版本)。此外,您需要非常小心,查询计划始终坚持搜索类型计划,而不是转入可能非常昂贵的表扫描。在这种情况下,即使不是绝对必要,我也可能会使用表提示(如果查询无法修改,则使用计划指南)。

另一种选择是在值的组合上重新创建聚集索引parentIdparentType如果该值组合是静态的并且通常随着时间的推移而增加。但是,如果parentType是整数类型会更好,并且如果基表很大或将变大,您可能希望考虑更改它以节省存储空间。考虑此更改还涉及查看它可能如何影响针对此表运行的其他类查询的索引。

如果这两种方法中的任何一种对于工作负载都不够快,请考虑使用 AppFabric 之类的东西实现数据缓存解决方案,它比每次需要数据时运行 SQL 查询更容易扩展。这可能是一个巨大的回报;成本增加了复杂性。