【问题标题】:When making indexes in PostgreSQL is required?何时需要在 PostgreSQL 中创建索引?
【发布时间】:2017-11-07 01:46:03
【问题描述】:

我有一列将存储我网站用户的用户名。我注意到 PostgreSQL 中的索引功能并想使用它。什么时候真正有意义地使用它们?

我开始觉得它们应该只在搜索改变时使用。例如,您不搜索原始用户名 (SELECT * FROM table WHERE username='user'),而是搜索 (SELECT * FROM table WHERE username=(lower(user)))。这种理解正确吗?

另外,如果对上述问题的回答是肯定的,那么这是否意味着 SQL 索引默认是自己的,只有当你需要一些特殊的索引时,你才需要运行CREATE INDEX

【问题讨论】:

  • 不,一般情况下 Postgres 默认不会索引任何内容。除此之外,你似乎在这里问了很多事情。 Postgres 支持常规列索引以及功能索引。因此,您的两个查询都可以从特定类型的索引中受益。
  • @TimBiegeleisen 默认不索引 PK 吗?
  • Postgres 中的 PK 应该自动为它们创建一个索引。
  • 关于使用 lower(user) 我建议你阅读这个出色的答案stackoverflow.com/a/7005656/2067753

标签: sql postgresql


【解决方案1】:

问:什么时候创建索引才有意义?

我们创建索引的原因主要有两个:1) 强制执行 UNIQUE 约束;2) 提高性能并减少争用。 (对于 PostgreSQL 来说,当我们声明一个 UNIQUE CONSTRAINT 时,数据库会自动创建一个 UNIQUE INDEX。)

问:这种理解正确吗?

不完全是,不。当我们使用谓词WHERE col = 'somevalue' 执行查询时,没有索引,数据库将需要评估表中的每一行。在非常大的桌子上,这可能是大量的工作。通过可用的适当索引,执行计划可以消除大量需要检查的行。这就是我们获得真正性能提升的地方。

想想这个比喻。当我们在字典中查找一个单词时,如果条目不是“按顺序”,我们将开始查看字典中的每个条目,并将我们正在查找的单词与每个条目进行比较,直到找到匹配项。

幸运的是,在大多数词典中,条目都是按字母顺序排序的。我们可以有效地利用这一点,很快就从考虑中排除大量页面,并为自己节省大量时间。如果我们正在寻找“表面上”这个词,我们知道我们可以从“O”开始。我们可以“跳过”以 A、B、...、N 开头的单词的页面上的所有条目,也可以“跳过”以 P、Q、...、Z 开头的单词的所有页面。

以类似的方式,数据库引擎可以节省大量工作,利用索引“跳过”它知道不能包含它正在查找的行的大量页面。

问:...默认情况下单独索引...?

对于 PRIMARY KEY 约束,是的,PostgreSQL 会自动创建索引。

对于 UNIQUE CONSTRAINT,是的,PostgreSQL 会自动创建索引。

所有其他索引必须显式声明(创建)。

我们通常希望在外键和列(或表达式,或列集)上创建索引,其前导列具有高基数/高选择性,并且在可搜索的谓词中被引用。

适当的索引可以显着提高性能;但是索引也是有代价的……索引维护需要额外的存储和处理,所以我们不应该随便创建单列索引。应注意评估正在执行(或我们计划执行)的实际查询并实施最有效地支持这些操作的索引。

【讨论】:

  • @nikolaevra:我试图对关系数据库索引进行总体概述,而不是深入研究杂乱无章的细节。有了这个概述,我们准备好讨论索引策略......什么是“好”索引,哪些索引不是很有用。这种讨论实际上取决于数据的特征和操作的特征。例如对于像SELECT upc FROM hughjasstable WHERE upc = 'someval' 这样的查询,upc 列上的索引将是最有利的,但查询也可以有效地利用(upc,lot,sz) 上的索引。
【解决方案2】:

PostgreSQL 提供了几种索引类型:B-tree, Hash, GiST and GIN。每种索引类型使用最适合不同类型查询的不同算法。默认情况下,CREATE INDEX 命令会创建适合最常见情况的 B-tree 索引。

B-trees 可以处理对可以排序为某种顺序的数据的相等和范围查询。特别是,当索引列涉及使用以下运算符之一进行比较时,PostgreSQL 查询计划器将考虑使用 B-tree 索引:

多列 B 树索引可用于涉及索引列的任何子集的查询条件,但当前导(最左侧)列存在约束时,索引效率最高。确切的规则是前导列上的等式约束,加上没有等式约束的第一列上的任何不等式约束,将用于限制扫描的索引部分。在索引中检查这些列右侧的列的约束,因此它们可以正确保存对表的访问,但不会减少必须扫描的索引部分。例如,给定 (a, b, c) 上的索引和查询条件 WHERE a = 5 AND b >= 42 AND c < 77,必须从 a = 5 和 b = 42up through the last entry with a = 5. Index entries withc >= 77 的第一个条目开始扫描索引跳过,但仍然必须扫描它们。这个索引原则上可以用于对 b 和/或 c 有约束而对 a 没有约束的查询——但是必须扫描整个索引,所以在大多数情况下,计划器更喜欢顺序表扫描而不是使用索引.

LOWER 函数接受一个字符串参数,例如 char、varchar 或 text,并将其转换为小写格式。如果参数是字符串可转换的,则使用 CAST 函数将其显式转换为字符串..

更多信息请见this

【讨论】:

    【解决方案3】:

    您应该索引经常搜索的列/案例。所以如果你经常查询lower(user),你应该为它创建一个索引。默认情况下,PGSQL 仅在主键上创建索引。请参阅 w3schools 的 link 了解更多信息

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 2016-05-27
      • 2020-06-10
      • 1970-01-01
      相关资源
      最近更新 更多