【问题标题】:Database indexes: Only selects!数据库索引:仅选择!
【发布时间】:2010-09-25 23:13:25
【问题描述】:

早安,

我有大约 4GB 的数据,分布在大约 10 个不同的表中。每个表都有很多列,每一列都可以是查询中的搜索条件。我根本不是DBA,对索引也不是很了解,但我想尽可能加快搜索速度。重要的一点是,任何时候都不会有任何更新、插入或删除(表每 4 个月填充一次)。在每一列上创建索引是否合适?记住:没有插入、更新或删除,只有选择! 另外,如果我可以将所有这些列设为整数而不是 varchar,我会在速度上有所不同吗?

非常感谢!

【问题讨论】:

    标签: sql-server database indexing sql-server-2000


    【解决方案1】:

    回答:不。单独索引每一列不是好的设计。索引在很多情况下需要包含多个列,并且针对不同的需求有不同类型的索引。

    其他答案中提到的调优向导是一个很好的入门(尤其是对于学习者)。

    不要试图通过它来猜测你的方式,或者希望你理解复杂的分析 - 获得针对你的具体情况的建议。我们似乎有几个线程在这里运行,它们对于特定情况和查询优化非常活跃。

    【讨论】:

    • 另外,不要忘记如果有很多列,优化器将花费更长的时间来确定哪些索引有帮助,哪些没有帮助。许多(可能是大多数)列不需要索引;只有那些在过滤条件中被积极使用的人才能使您受益。
    • @Jon,这就是为什么真正的数据库(比如 DB2 :-) 有 runstats 等,因此它们可以让优化器跟上表中的数据分布。无论有多少,优化器都可以轻松选择最佳索引。
    • @doofle,问题指出每一列都需要搜索 - 因此为了最大速度,它们都应该被索引,以及多列组的索引。
    • @Pax,他在询问每列的单字段索引。如果一列是复合索引中的第一列,则它不需要自己的另一个索引。此外,例如,布尔字段索引被忽略,因此对于这些情况而言,一揽子规则过于幼稚。
    • @doofle,阅读问题 - 没有位域,每一列都需要搜索。
    【解决方案2】:

    您是否看过运行 Index Tuning Wizard? 会根据工作负载为您提供索引建议。

    【讨论】:

    • @KiwiBastard(可能是新西兰的任何人,来自 Oz 的你好 :-),很好的答案,+1。向导是即时进行统计(以使优化器保持最新)还是只是建议将新的 DDL 命令应用于表? DB2 有 runstats,它根据表中的数据更改计划路径。
    【解决方案3】:

    绝对不是。

    您必须了解索引的工作原理。如果你有一个表,比如 1000 条记录,但它是一个 BIT,并且可以有两个值之一,如果你只对该列和该列进行索引,它将毫无价值,因为它的选择性不够。当您对列进行索引时,要非常清楚将在表上执行哪些类型的选择。当您在列上创建索引时,该索引的选择性是否足以让优化器有效使用?

    到那时,您很可能会发现,一些精心挑选的复合索引将大大优于每列上许多单个索引的解决方案。黄金法则:如何查询数据库将决定如何创建索引。

    【讨论】:

    • @Dave,问题是针对 varchars 的,每一列都是可搜索的,因此,虽然您的回答对于索引的一般问题很有用,但它并不真正适用于这个问题。您的黄金法则是正确的,但您已经拥有做出决定所需的信息。
    • 列中包含 VARCHAR 并不意味着索引是选择性的! BIT 的例子只是用来说明一些显然不能选择性的东西。如果您的 VARCHAR 列每 1000 行只有 2 个或 3 个值,情况也是如此...
    【解决方案4】:

    缺少两条信息:每列中有多少不同的值,以及您使用的是哪个 DBMS。如果您使用 Oracle 并且每列的不同值少于几千个,则可以创建位图索引。这些对于精确匹配来说非常节省空间和执行效率。

    否则,这是一种权衡:每个索引将添加与包含相同数据的单列名称大致相同的空间量,因此您的空间需求基本上会增加一倍(可能是 2.5 倍)。所以可能是 10G,这不是很多数据。

    然后是您的 DBMS 是否会有效地合并多个基于索引的选择的问题。很有可能它不会,除非您对选择的每一列都进行自联接。

    最佳答案:在较小的数据集上尝试(这样您就不会花费所有时间来构建索引)并看看它是如何工作的。

    【讨论】:

      【解决方案5】:

      如果您从表中选择的一组列大于所选索引中的列所覆盖的列,那么您将不可避免地在查询计划中引发书签查找,这是查询处理器必须检索非- 使用关联非聚集索引中叶行的参考 ID 覆盖聚集索引中的列。

      根据我的经验,书签查找确实会降低查询性能,因为需要额外的读取量以及必须单独解决聚集索引中的每一行的事实。这就是为什么我尝试使 NC 索引尽可能覆盖,这在所需查询计划众所周知的较小表上更容易,但如果您有包含大量列的大表,并且预期有任意查询,那么这可能不会是可行。

      这意味着您只有使用任何类型的 NC 索引才能物有所值,前提是该索引可以覆盖,或者选择一个足够小的数据集以降低书签查找的成本 - 实际上,您可能会发现如果与聚集索引扫描相比,所有列都已经可用,那么查询优化器甚至不会查看您的索引。

      因此,除非您知道索引会优化给定查询的结果,否则创建索引是没有意义的。因此,索引的值与它可以针对给定表优化的查询百分比成正比,这只能通过分析正在执行的查询来确定,这正是索引调整向导为您所做的。

      总结一下:

      1) 不要索引每一列。这是经典的过早优化。您不能提前为所有可能的查询计划优化带有索引的大表。

      2) 在通过索引调整向导捕获并运行基本工作负载之前,不要为任何列建立索引。此工作负载需要代表您的应用程序的使用模式,以便向导可以确定哪些索引实际上有助于您的查询性能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-28
        • 2015-09-17
        • 1970-01-01
        • 2021-09-11
        • 1970-01-01
        • 1970-01-01
        • 2022-01-27
        相关资源
        最近更新 更多