【问题标题】:How to know when to use indexes and which type?如何知道何时使用索引以及使用哪种类型?
【发布时间】:2011-01-25 15:26:38
【问题描述】:

我搜索了一下,没有看到任何类似的问题,所以这里。

您如何知道何时将索引放入表中?您如何决定将哪些列包含在索引中?什么时候应该使用聚集索引?

索引会降低select 语句的性能吗?多少索引太多了,需要多大的表才能从索引中受益?

编辑:

列数据类型呢?可以在varchardatetime 上建立索引吗?

【问题讨论】:

  • "是否可以在 varchar 或 datetime 上建立索引?"我有一个表,其中聚集索引位于日期时间(尽管我们只使用日期部分),因为表上的所有查询都限制为开始/结束日期对,并且数据的选择性足够高以使其不错的选择。

标签: sql performance database-design indexing


【解决方案1】:

嗯,第一个问题很简单:

什么时候应该使用聚集索引?

总是。时期。除了极少数罕见的边缘情况。对于每个操作,聚集索引使表更快。是的!确实如此。有关背景信息,请参阅 Kim Tripp 的优秀 The Clustered Index Debate continues。她还提到了她对聚集索引的主要标准:

  • 静态(永不改变)
  • 独一无二的
  • 如果可能的话:不断增加

INT IDENTITY 完美地实现了这一点 - GUID 没有。有关详细背景信息,请参阅 GUID's as Primary Key

为什么要缩小?因为在同一张表的每一个非聚集索引的每一个索引页上都添加了聚集键(为了能够实际查找到数据行, 如果需要的话)。您不想在集群键中包含 VARCHAR(200)....

为什么是唯一的?? 见上文 - 群集键是 SQL Server 用于唯一查找数据行的项和机制。它必须是独一无二的。如果您选择一个非唯一的集群键,SQL Server 本身会为您的键添加一个 4 字节的唯一符。小心那个!

下一步:非聚集索引。基本上有一个规则:引用另一个表的子表中的任何外键都应该被索引,它会加快 JOIN 和其他操作。

此外,任何具有 WHERE 子句的查询都是不错的候选 - 选择那些首先执行的查询。在 ORDER BY 语句中,对出现在 WHERE 子句中的列进行索引。

下一步:测量您的系统,检查 DMV(动态管理视图)以获取有关未使用或缺失索引的提示,并一遍又一遍地调整您的系统。这是一个持续的过程,你永远不会完成!有关这两个 DMV(缺失和未使用的索引)的信息,请参见 here for info

另一个警告:使用大量索引,您可以使任何 SELECT 查询运行得非常快。但与此同时,必须更新所有相关索引的 INSERT、UPDATE 和 DELETE 可能会受到影响。如果你只选择 - 发疯!否则,这是一种微妙而微妙的平衡行为。您总是可以难以置信地调整单个查询 - 但系统的其余部分可能会因此而受到影响。不要过度索引您的数据库!放置一些好的指标,检查并观察系统的行为,然后可能再添加一两个,然后再次:观察整体系统性能如何受此影响。

【讨论】:

  • +1 表示这是一个持续的过程,而不是你只做一次的事情。
  • 实际上,我们的数据库既是 Sql Server 又是 Postgres。所以你对那里的实现有点过于具体了,但除此之外还是一个很好的解释。
  • 是的,考虑到 Oracle 本身没有集群索引(它们确实有索引组织表和 b 树集群),并且 DB2 for z/OS 上的集群索引被用作指导集群数据,但不是法律。如果优化器不能很好地处理结果集的基数,索引可能会进一步减慢选择速度——完全扫描可能比索引访问成本更低。
【解决方案2】:

经验法则是主键(隐含并默认为集群)和每个外键列

还有更多,但您可能比使用 SQL Server 的 missing index DMV 做得更糟

如果优化器做出错误的选择,索引可能会减慢 SELECT 的速度,并且可能有太多。太多会减慢写入速度,但也有可能重叠索引

【讨论】:

    【解决方案3】:

    回答我能回答的问题我想说,每张表,无论多小,都将始终受益于至少一个索引,因为您必须至少有一种方法可以让您有兴趣查找数据;否则为什么要存储它?

    添加索引的一般规则是,如果您需要使用特定字段或一组字段在表中查找数据。这会导致索引数量过多,通常您拥有的索引越多,插入和更新速度就越慢,因为它们还必须修改索引,但这完全取决于您如何使用数据。如果您需要快速插入,则不要使用太多。在报告“只读”类型的数据存储时,您可以拥有多个这样的数据存储,以加快您的所有查找速度。

    不幸的是,没有一个规则可以指导您使用的索引的数量或类型,尽管您选择的数据库的查询优化器可以根据您正在执行的查询给出提示。

    对于聚集索引,它们是您只能使用一次的 Ace 卡,因此请谨慎选择。值得计算您正在考虑放置的字段的选择性,因为数据的选择性非常低,因此将其放置在布尔字段(人为示例)之类的东西上可能会浪费。

    【讨论】:

    • @Tony "否则为什么要存储它" 系统日志中的日志插入非常频繁(每分钟多次)但只有在需要日志的地方发生某些事情时才会检索数据(例如,像每两个月一次)
    • @Earlz:公平点,但是当您查看日志时,索引将帮助您搜索日志表包含的数百万行。我可以看到我对那个声明有点过分了:)
    【解决方案4】:

    这确实是一个非常复杂的问题,尽管一个很好的起点是索引您将过滤结果的任何列。 IE。如果您经常按销售价格将产品分组,请索引 products 表的 sale_price 列以缩短该查询的扫描时间,等等。

    【讨论】:

      【解决方案5】:

      如果您基于列中的值进行查询,您可能希望为该列建立索引。

      SELECT a,b,c FROM MyTable WHERE x = 1
      

      你会想要一个 X 上的索引。

      一般情况下,我会为经常查询的列添加索引,并在查询多个列时添加复合索引。

      索引不会影响 SELECT 的性能,但如果每个表的索引列过多,它们可能会减慢 INSERTS(或 UPDATES)的速度。

      根据经验 - 当您发现自己说 WHERE a = 123(在本例中为“a”的索引)时,首先添加索引。

      【讨论】:

        【解决方案6】:

        您应该在用于选择和排序的列上使用索引 - 即 WHERE 和 ORDER BY 子句。

        如果有很多 select 语句,并且您在未编入索引的列上使用 WHERE 和 ORDER BY,则索引可以减慢速度。

        至于表的大小 - 几千行及以上将开始显示对索引使用的真正好处。

        话虽如此,有自动化工具可以做到这一点,SQL Server 有一个Database Tuning Advisor 可以帮助解决这个问题。

        【讨论】:

        • ITW 现在在 SQL Server 2005 及更高版本中称为“数据库优化顾问 (DTA)”
        猜你喜欢
        • 2011-05-04
        • 1970-01-01
        • 2013-08-17
        • 1970-01-01
        • 2013-01-02
        • 2014-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多