【问题标题】:When to create a new SQL Server Index?何时创建新的 SQL Server 索引?
【发布时间】:2008-10-30 14:11:44
【问题描述】:

显然(我认为),在 BIT 列上创建索引是不必要的。但是,如果您有一个需要搜索的列,其中每个值都可能是唯一的,例如 BlogPostStreetAddress 或其他什么,那么索引似乎是合适的(再次,我认为)。

但是截止点是多少?如果您期望有 10,000 行并且其中将有大约 20 个唯一值,该怎么办。是否应该创建索引?

提前致谢。

【问题讨论】:

    标签: sql database tsql


    【解决方案1】:

    对此的最佳答案是分析您的查询并查看索引是否改进了您的查询。回答这个问题的困难在于几乎不可能概括查询优化器的行为。

    也就是说,经验法则是,如果您对表的给定查询的选择性为 10% 或更少,那么您很可能会从索引中受益。因此,在您的示例中,如果您的值均匀分布,您可能会从索引中受益。但是,考虑到您的表很小,因此您的性能提升可能可以忽略不计。

    这不是一个硬性规定,因为有很多因素可以改变 10% 的数字,包括使用聚集索引或其他索引类型、行的大小、如果某些列不是内联的、查询结构等。

    另外请记住,插入带有索引的表会显着降低性能。如果此表经常更新或附加,则索引的速度提升可能会被较慢的插入和更新所抵消。

    请参阅 Tablescan vs Index access 上的 MSDN 文章。

    编辑:正如其他人指出的那样,如果您正在执行聚合查询,例如计算特定值出现的次数,您的查询可能会受益于索引。如果您经常对特定列进行排序,您也可能会受益。

    【讨论】:

      【解决方案2】:

      詹姆斯一针见血。我将补充一点,根据您使用表的方式,即使是位列也可能受益于索引。例如,如果您需要计算一天中多次出现 1 的行数,那么索引可能会很有用。索引并不总是用于查找单个记录 - 它们也可以用于聚合。

      【讨论】:

      • 这行不通。我从痛苦的经历中知道,SQL Server 不会使用基数为 2 的索引,即使 1 条记录的值为“1”且 1000 万条记录的值为“0”。
      • @doofledorfer:我确信这是正确的。你有一个实际的例子吗?
      【解决方案3】:

      基数低的索引非常有问题。如果只有几个可能的值,SQL Server 几乎总是索引扫描,无论比例如何。

      示例:我有一个带有 State 字段的表,它只接受值“A”、“N”和“R”(用于 Active、New 和 Retired。)通常您会接近一个条件,其中95% 为“R”,4+% 为“A”,少数为“N”。 SELECT WHERE state = 'N' 无论如何都会进行表扫描。

      但是 - 有一个新的索引类型称为 Filtered Index,,它最终处理了这种情况。当您想要排除具有 NULL 值的记录时,它也很方便。

      【讨论】:

        【解决方案4】:

        在您建议的列中,有理由为数据创建参考或查找表以避免数据冗余。这将使您的列成为外键,指向新查找表的 PK。

        所有外键列都应该被索引。

        否则,我会避免在正常情况下在此类列上放置索引。

        【讨论】:

          【解决方案5】:

          没有必要在 BIT 列上创建索引。

          你会感到惊讶。

          我必须为如下查询创建一个涉及位列的索引:

          SELECT foo.Name FROM foo WHERE foo.Active = 1
          

          不过,表中有大约 300,000 行。

          【讨论】:

          • 与其他可能的值相比,Active=1 代表的行的比例是多少?我怀疑它只是整个表的一个相对较小的子集。
          • 它不起作用。我已经尝试过了,并让 MS 确认了 - 无论比例如何,都会忽略低基数指数。
          【解决方案6】:

          我想说这完全取决于表的使用方式和整体系统要求。例如,如果它是大型 JOIN 的一部分,并且父级是一个巨大的报表类型表,那么您肯定需要索引。如果与数据库中的其他表相比它相对较小,并且它被大量插入并且很少读取,那么可能不需要索引。

          但是,整个数据库的操作范围与要分配的可用资源是关键的决策因素。这是该表 + 可能的索引在整个系统中与所有其他表及其要求相比的行为方式。如果您不牢记大局,您可能会为了应用任意规则而尝试应用任意规则来杀死整个系统。

          【讨论】:

            【解决方案7】:

            如果您开始遇到查询之间的死锁,通常在 SELECT 和 INSERT/UPDATE 之间,您还应该仔细检查您的索引。选择不当的索引会导致死锁,就像根本没有索引一样。有关更多信息,请参阅this knowledge base 文章。通常,添加索引或修改其包含的列将有助于解决此类死锁。请务必检查受影响查询的查询计划。

            【讨论】:

              【解决方案8】:

              最好的方法之一是在 SQL Server 中使用 mvp 视图 我建议不要重启你的服务器一周然后运行这个查询:

              USE master; 
              Go
              SELECT d.database_id,
                d.object_id,
                d.index_handle,
                d.equality_columns,
                d.inequality_columns,
                d.included_columns,
                d.statement AS fully_qualified_object,
                gs.*
              FROM   sys.dm_db_missing_index_groups g
              JOIN   sys.dm_db_missing_index_group_stats gs ON   gs.group_handle = g.index_group_handle
              JOIN   sys.dm_db_missing_index_details d ON   g.index_handle = d.index_handle
              
              Go
              
              SELECT mig.index_group_handle,
                mid.index_handle,
                migs.avg_total_user_cost AS AvgTotalUserCostThatCouldbeReduced,
                migs.avg_user_impact AS AvgPercentageBenefit,
                'CREATE INDEX missing_index_' + CONVERT (varchar, mig.index_group_handle)
                + '_' + CONVERT (varchar, mid.index_handle)
                + ' ON ' + mid.statement
                + ' (' + ISNULL (mid.equality_columns,'')
                + CASE
                       WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns
                       IS NOT NULL THEN ','
                       ELSE ''
                  END
                  + ISNULL (mid.inequality_columns, '')
                + ')'
                + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS  create_index_statement
              FROM sys.dm_db_missing_index_groups mig 
              INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle =  mig.index_group_handle
              INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle =  mid.index_handle
              Order By migs.avg_user_impact Desc
              

              然后验证您的表并创建请求索引。

              【讨论】:

                【解决方案9】:

                这里已经发布了很好的答案......只需添加我的两分钱......执行缺失索引DMV并查看您提到的表是否被列为创建新索引的候选并查看定义索引。

                来自Are you using SQL's Missing Index DMVs?

                SELECT
                  migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
                  'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle)
                  + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']'
                  + ' ON ' + mid.statement
                  + ' (' + ISNULL (mid.equality_columns,'')
                    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END
                    + ISNULL (mid.inequality_columns, '')
                  + ')'
                  + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement,
                  migs.*, mid.database_id, mid.[object_id]
                FROM sys.dm_db_missing_index_groups mig
                INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
                INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
                WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
                ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-08-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-10-05
                  • 1970-01-01
                  • 2021-08-05
                  • 1970-01-01
                  • 2017-04-09
                  相关资源
                  最近更新 更多