代码之家  ›  专栏  ›  技术社区  ›  smirkingman

数据库索引:一件好事,一件坏事,还是浪费时间?

  •  13
  • smirkingman  · 技术社区  · 14 年前

    这里经常建议添加索引来解决性能问题。

    (我说的只是阅读和查询,我们都知道索引会使编写速度变慢)。

    多年来,我在DB2和MSSQL上多次尝试这种补救方法,结果总是令人失望。

    我的发现是,不管索引有多“明显”,都会让事情变得更好,结果是查询优化程序更聪明,而我聪明地选择的索引几乎总是让事情变得更糟。

    我应该指出,我的经历主要与小表(100000行)有关。

    谁能提供一些关于索引选择的脚踏实地指南?

    正确的答案是一个建议列表,如:

    • 从不/总是索引记录小于/大于NNNN的表
    • 从不/始终考虑多字段键上的索引
    • 从不/始终使用聚集索引
    • 从不/始终在单个表上使用多于NNN的索引
    • 从不/总是在[我很想了解的一些神奇情况]时添加索引

    理想情况下,答案会给出一些有指导意义的例子。

    8 回复  |  直到 14 年前
        1
  •  18
  •   Keng    14 年前

    指标有点像化疗……太多了,它会杀死你……太少了,你就会死……做错事,你就会死。你要知道多少次,多少次,什么样的方式才能让它不杀你。

    你的硬件,平台,环境,负载都起作用。所以回答你的问题。。

    是的,有时可能。

        2
  •  12
  •   HLGEM    14 年前

    根据经验,主键和外键需要被索引。通常,主键只是通过这样定义来索引,但FKs并不在每个数据库中(它们肯定不在SQL Server中,我不能真正代表其他dbs)。您将在连接中使用它们,因此定义它们通常对性能至关重要。

    现在,如果有在where子句中经常使用的字段,那么这些字段可以从索引中获益,还可以提供以下内容:

    • 首先,字段必须具有 价值观。位场或具有 只有2或3个值几乎永远不会 使用索引。

    • 其次,您编写的查询必须是可搜索的。也就是说,它们必须设计为使用索引。我怀疑,如果您从未从看起来可能的索引候选中获得性能改进,那么您可能有一些不可搜索的查询。例如,将“WHERE Name like'%Smith''作为WHERE子句。如果不知道第一个字符,优化器就不能使用索引。

    小表很少从索引中获益。如果优化器可以将整个东西保存在内存中,那么这样做通常更快。如果您使用的是数百万个记录表,您将看到索引是关键的。

    索引可能非常复杂,如果您对该主题感兴趣,我建议您在性能优化方面找到一本好书,并对其进行深入阅读。

        3
  •  5
  •   Gilbert Le Blanc    14 年前

    从未使用过的索引会浪费磁盘空间,还会增加插入/更新/删除时间。最好先定义集群索引,然后再定义 当你发现自己在写的时候 WHERE 条款。

    我看到的一个常见的索引错误是人们想知道当索引定义为 col1 ASC, col2 ASC, col3 ASC . 如果有多列索引,则 哪里 子句必须使用索引中的第一列,或索引中的第一列和第二列,依此类推。

    如果需要通过col2访问数据,则需要一个额外的索引,该索引定义为 col2 ASC .

    对于小型域表,有时进行表扫描比使用索引从表中读取行快。这取决于数据库计算机的速度和网络的速度。

        4
  •  3
  •   Keng    14 年前

    你需要索引。只有使用索引,您才能足够快地访问数据。

    尽可能短:

    • 为经常筛选(或分组)的列添加索引。(如州或名称)
    • like sql函数可以使DBMS不使用索引。
    • 仅在具有许多不同值的列上添加索引(例如,没有布尔字段)
    • 向外键添加索引是常见的,但并不总是需要。
    • 不要在非常短的表中添加索引
    • 当您不知道索引应该如何提高性能时,不要添加索引。

    最后:查看执行计划以决定如何优化查询。

    只为一个关键查询添加索引。在本例中,您将准确地添加所讨论查询中所需的索引(多列索引)。

        5
  •  2
  •   TomaszSobczak    14 年前

    基本上,当数据库收集数据时,它的活动索引必须随流而变化。表上可能有很好的索引,但是在超过XXX记录之后,同一个表中的同一个索引是无用的,在这种情况下应该重构它。

    要优化和快速的数据库,唯一的方法是一直监视它,并随着记录的到来而重构它。

    前段时间我得到的现实生活的例子是受某个时间范围(在A和B之间创建)限制的超快速查询和时间范围不同的超慢速查询。相同的查询,相同的数据库,相同的应用程序,只有一个时间范围的差异。

        6
  •  2
  •   user151323user151323    14 年前
    Always use clustered indexes.
    

    事实上你不得不使用它们。表中的数据将以某种特定的顺序排列在磁盘上,无论如何,它不能保存为一堆或其他东西。您有机会指定这些数据的确切布局。为什么烧了它?

    如果有一个表追加了新记录,并且观察到这些记录中的某些值总是增长(如StackOverflow问题编号),请从中创建一个聚集索引。然后,新的数据将不会插入中间,而是基本上附加到磁盘上的文件中,这是一个相对便宜的操作。

        7
  •  1
  •   Jeffrey L Whitledge    14 年前

    如果一个表被期望成为一个连接的目标,那么最好在该表上有一个聚集索引,以便可以通过数据页顺序执行连接。聚集索引中的列(在某些数据库系统上)将包含在该表的所有其他索引中,因为这些是索引将用于引用表数据的值。为了防止其他索引变得太大,聚集索引中的列应该尽可能窄,因此最好在聚集索引中只使用数字数据类型,而不是字符数据类型。一般来说,更少的列比更多的列要好,但是请注意 int 列(每行12字节)比一列好得多 nvarchar(32) 列(可能是每行64字节)。

    如果聚集索引很窄,那么即使在非常大的表上,一些额外的索引也不会对性能产生太大的负面影响。

        8
  •  0
  •   Charles Bretana    14 年前

    你好像混淆了两个概念。 添加索引 * 通常地 可以 只会使读取查询更快,很少(几乎从不)慢。添加索引不会强制查询优化器使用它。只有当它认为自己能从中受益时,它才会使用它,而且它通常对这些决定非常聪明。

    当然,对于插入/更新,每个索引都会对性能造成更大的影响。。。但是在频谱的另一端,比如说只读数据库(比如每月分发的USPS地址数据库),在操作使用中不会有插入/更新,所以附加索引的唯一负面影响是它们占用的磁盘空间。

    这完全不同 指定 查询优化器使用一个索引,实际上覆盖了它自己的操作。。。这可能会降低查询速度。

    编辑:编辑以消除过度文字读者误解的机会。