创建 2 个具有相同键列但不同包含列的非聚集索引

Posted

技术标签:

【中文标题】创建 2 个具有相同键列但不同包含列的非聚集索引【英文标题】:Creating 2 non-clustered indexes with same key columns but different included columns 【发布时间】:2014-08-25 13:19:09 【问题描述】:

我有一个从 SQL Server MCSA 培训工具包借来的存储过程,它显示我的数据库中缺少索引。结果中有两条建议:

    两个键列 + 2 个包含 相同的两个键列 + 7 包括

我的问题是,创建两个具有相同键的非聚集索引是否是一种好习惯,即使它们具有不同的包含列?

创建一个包含所有列(9 列)的不是更好吗?

注意:第二个索引推荐还包括第一个索引推荐中的所有字段。

谢谢

【问题讨论】:

这取决于如何处理与性能相关的问题:例如,您有一个最重要的查询,您希望比任何其他查询执行得更快,它包含 4 列或更少的列和两列在哪里条件。那么你应该保留两者,因为它会快速加载到缓存中并且需要更少的空间,因此更少的逻辑读取, 有趣,我想知道执行计划是否会从两者中选择正确的索引。例如,如果它使用公共键并且需要返回包含在两个索引中的列,它会选择包含较少的列还是不包含。请记住部分修辞问题...谢谢。 好吧,我创建了两个索引,只要我不从较大索引中包含的列中选择字段,执行计划就会使用包含最少的索引。它完美无缺。使用包含更多包含的索引的成本更高(这是合乎逻辑的),因此我会说两个索引比一个好。主要缺点是写入速度可能会慢一些,并且需要更多存储空间。 【参考方案1】:

创建一个包含所有列(9 列)的不是更好吗?

这取决于不同列的相对大小。 假设您的表格有这 11 列:

indexedCol1 int
indexedCol2 int
col1        int
col2        int
col3        varchar(1000)
col4        varchar(1000)
col5        varchar(1000)
col6        varchar(1000)
col7        varchar(1000)
col8        varchar(1000)
col9        varchar(1000)

包含col1col2 的索引将具有大小略大于16 字节的叶子。每 8kb 页面可以容纳大约 500 个索引叶。检索 5000 行将需要 10 次页面读取

包括col1col9 的索引将具有最大 大小略高于7032 字节的叶子。假设这些 varchar 列平均已满 10%。一行的平均大小为 700 字节。每个 8kBytes 页面可以容纳 11 个索引叶子。 检索 5000 行将需要大约 450 页读取。会慢很多。

这当然是一个例子。但我认为这是处理问题的方法。

例如,如果它使用公共密钥,需要返回 包含在两个索引中的列,它会选择一个 less 包含与否。

我会这么说。但这只是猜测。

【讨论】:

喜欢这个答案。这些字段是小于 40 个字符的 int 或 nvarchar,但是我真的很喜欢您对此的思考。我对索引性能有点强迫症,这很有趣。非常感谢。 PS - 稍后我将测试执行计划,看看它从两个索引中选择了哪一个。将向所有人更新结果。【参考方案2】:

创建一个包含所有列(9 列)的不是更好吗?

这取决于您计划的查询。例如,您的表 T 在 A、B、C 列上有一个索引。

查询

select * from T where C = ...

不会使用这个索引,因为A和B列没有where-predicated,C列不是这个索引的第一个。

【讨论】:

对不起,我应该提到两个推荐的索引都是基于经常使用的查询。此外,第二索引推荐还包括第一索引推荐中的所有字段。希望这有助于更好地了解困境。

以上是关于创建 2 个具有相同键列但不同包含列的非聚集索引的主要内容,如果未能解决你的问题,请参考以下文章

创建带包含列的索引 sqlserver

Create Index语句的Include作用

堆上的非聚集索引与聚集索引的性能 [关闭]

索引键列和包含性列

如何创建具有一个索引键列和多个值列的字典

数据库索引是什么