【问题标题】:Need advice in choosing right columns for clustered index in SQL Server 2012 (among list of given options)在为 SQL Server 2012 中的聚集索引选择正确的列时需要建议(在给定选项列表中)
【发布时间】:2017-07-24 14:54:01
【问题描述】:

我使用的是 SQL Server 2012。

所以这里是表格

GroupCategoryType 
(
  GroupCategoryTypeID int identity(1,1) not null, --It is also a PK
  GroupTypeID int,
  id int,
  GroupCategoryID int,
  UserID int
)  
-- Total Rows around 60,000

我正在此表上设置自定义聚集索引,因为 GroupCategoryTypeID 键上的现有聚集索引没有太大帮助(因为没有对此 PK 进行过滤/加入)。

我选择了(GroupCategoryID, GroupTypeID, ID),因为这三个是最常用的in ('join','where')
我在这里提到的顺序是按照它们的使用频率递减顺序。

关于这个(即将成为)聚集索引的几点需要注意的是:

  1. GroupTypeID 可以是 1 或 2;它具有最少的唯一值频率,即 2
    GroupCategoryId 具有中等频率的唯一值,即 2200 # 个唯一值 ID 具有最高频率的唯一值,即 30,000

  2. 这些列的对或三联的可能组合都不是唯一的。
    以下是一些统计数据:

    1. group by GroupCategoryId,id 返回 count(*) 从 2 到 1600,总共 55,000 行中有 700 行,其余 54,300 行是唯一的。
      为了更清楚,我使用了select groupCategoryid,id,count(*) as total from GroupCategoryType group by groupCategoryid,id order by total desc,这返回了 55000 行。
    2. group by GroupCategoryId,GroupTypeID 返回计数 (*) 范围为 2 到 3200,总共 2500 行中有 700 行,其余 1800 行是唯一的。
    3. group by GroupTypeID,ID 返回计数 (*) 范围为 2 到 1600,总共 42000 行中有 6500 行,其余 40,400 行是唯一的。
    4. group by GroupCategoryid,grouptypeid,id(三元组)对于总共 52000 行中的 700 行返回从 2 到 1600 的计数 (*),其余 51,300 行是唯一的。

现在,我的问题是:

  1. 根据所有这些统计信息,最佳聚集索引应该是什么? (请记住,GroupTypeid 只有两个唯一值)
  2. 我知道 SQL Server 本身会添加一个唯一性来使行唯一,但它会将此键添加到所有行(甚至是那些已经唯一的行)还是只是重复的行?
  3. 考虑到上面的第 2 点,我是否应该将 GroupCategoryTypeID 添加到聚集索引中以使所有组合都唯一?
  4. 例如,如果在 where 子句中有一个仅使用 (col2,col3) 或 (col1,col3) 或仅 (col3) 的查询,是否仍会使用 (col1,col2,col3) 的聚集索引? 如果不是,是否应该在 (col2,col3) 或 (col1,col3) 上创建非聚集索引,并为 (col3) 单独创建此类情况的最佳解决方案?

【问题讨论】:

  • 这完全取决于您使用的 SQL Server 版本,2016 年发布了一个非常高效的列存储索引 - 您需要查看版本特定的索引以及何时应该使用每个索引。
  • 为什么要使用聚集索引?为什么不只是一个常规索引?
  • @jimmy8ball :我现在在最初的问题中提到了 SQL Server 2012。谢谢。
  • 对于数据库,您的表很窄,60k 行很小。我会在 PK 上保留聚集索引,让它运行一周左右,然后检查数据库引擎优化顾问以查看它推荐的索引
  • 此表WHERE Col1 = @param1 AND ...的行的主要数据访问路径是什么?

标签: sql sql-server sql-server-2012


【解决方案1】:

根据所有这些统计数据,最佳聚集索引应该是什么? (请记住,GroupTypeid 只有两个唯一值)

最好的决定方法是分析执行计划,在我的脑海中,我对这些键的选择是(GroupTypeID, GroupCategoryID, ID)。通过这种配置,head 可以读取更多的线性避免跳转,因为只有两个寄存器

我知道 SQL Server 本身会添加一个唯一标识符以使行唯一,但它会将此键添加到所有行(甚至是那些已经唯一的行)还是只是重复的行?

SQL Server 插入的唯一标识符用于控制 它们不用作普通主键的事务。

考虑到上面的第 2 点,我是否应该将 GroupCategoryTypeID 添加到聚集索引中以使所有组合都唯一?

不一定,你的聚集索引一定是最适合你使用的并不总是PK,在某些情况下,你可以拥有一个不唯一的聚集索引。这不常见,但有可能。

如果是前。有一个查询,在 where 子句中仅使用 (col2,col3) 或 (col1,col3) 或仅 (col3),是否仍会使用 (col1,col2,col3) 的聚集索引?如果不是,那么是否应该在 (col2,col3) 或 (col1,col3) 上创建一个非聚集索引,并为 (col3) 单独创建一个非聚集索引,这是此类情况的最佳解决方案?

再次,您需要检查执行计划,在某些环境中,具有 60k 寄存器的表太小而 SQL Server,在其他环境中,该表太大以至于您需要大量索引。

【讨论】:

    【解决方案2】:

    有几次我成功地根据 int/bigint 和唯一值的最佳实践创建了聚集索引。在一种情况下,我建议在一个甚至不接近唯一的 bigint 列上创建一个聚集索引,它解决了我们遇到的一个大阻塞问题。

    对于有问题的表,最密集的查询在某些情况下会使用该列作为过滤器选择数百万行。起初,我们在另一个在表中唯一的 bigint 列上有聚集索引,它产生了很多锁定问题。

    我会查看您对该表的查询,并创建可提供最佳性能的聚集索引,而不必按照纸上的最佳实践。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      • 2019-04-04
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多