是否有一种很好的方法来判断在Postgres中创建数据库索引的成本(较慢INSERTS
,构建索引的时间,重新索引的时间)是否值得获得性能提升(更快{{1} }})?
答案 0 :(得分:5)
我实际上不同意Hexist。 PostgreSQL的规划器非常好,它支持基于物理顺序扫描对表文件的良好顺序访问,因此索引不一定有用。此外,在许多情况下,计划者必须选择一个索引。此外,您已经为唯一约束和主键创建主键。
我认为PostgreSQL的一个很好的默认位置(MySQL btw完全不同!)是等到你需要一个索引来添加一个,然后只添加你最需要的索引。然而,这只是一个起点,它假设缺乏查看查询计划的一般经验,或者缺乏对应用程序可能去向的理解。在这些方面有经验很重要。
通常,如果您的表可能跨越10页以上(即40kb的数据和标题),那么外键是个好主意。可以明确地假设这些。跨越1页的小型查找表应该从不具有非唯一索引,因为这些索引永远不会用于选择(没有查询计划胜过单页的顺序扫描)。
除此之外,您还需要查看数据分布。索引布尔列通常是一个坏主意,并且有更好的方法来索引与布尔搜索相关的事物(部分索引是一个很好的例子)。类似地,索引常用函数输出有时似乎是一个好主意,但情况并非总是如此。考虑:
CREATE INDEX gj_transdate_year_idx ON general_journal (extract('YEAR' FROM transdate));
这不会有太大作用。但是,如果通过递归CTE与稀疏索引扫描配对,则transdate索引可能会有用。
一旦基本索引到位,那么问题就变成了你需要添加的其他索引。这通常最好留待以后使用案例审查,而不是最初设计的。人们发现在PostgreSQL上使用较少的索引可以显着提高性能,这种情况并不少见。
要考虑的另一个主要问题是您创建了哪种索引,这些索引通常是特定于用例的。例如,如果常规对域很重要,并且如果您经常基于初始元素进行搜索,那么数组记录上的b树索引可能有意义,但如果常规不重要,我会建议使用GIN索引,因为btree会做得很少(当然这是一个原子红旗,但有时候在Pg中有意义)。即使常规很重要,有时你也需要GIN索引,因为你需要能够进行交换式扫描,就好像不是普通性一样。如果使用ip4r存储cidr块并使用EXCLUDE约束来确保没有任何块包含任何其他块(实际扫描需要使用重叠运算符而不是包含运算符,因为您不知道哪一侧是操作员将在上面找到违规行为。
这又是一些特定于数据库的。例如,在MySQL上,Hexist的建议是正确的。但是,在PostgreSQL上,关注问题是件好事。
就测量而言,最好的工具是EXPLAIN ANALYZE
答案 1 :(得分:3)
一般来说,除非你有一个日志或归档表,你不经常选择(或者如果他们需要一段时间才能运行),你应该索引你的select / update / deelete语句将使用的任何内容在where子句中。
然而,这并不像看起来那么简单,因为只是因为在where子句中使用了列并且索引,并不意味着sql引擎将能够使用索引。使用postgresql的EXPLAIN
和EXPLAIN ANALYZE
功能,您可以检查选择中使用了哪些索引,并帮助您确定列上的索引是否可以帮助您。
这通常是正确的,因为没有索引,您的选择速度会从某些O(log n)查找操作下降到O(n),而您的插入速度只会从cO(log n)提高到dO(log n)其中d通常小于c,即你可以通过没有索引加快插入速度,但如果它们没有编入索引你就会杀死你的选择速度,所以拥有一个索引几乎总是值得的如果您要选择反对它,请使用您的数据。
现在,如果你有一些小表,你进行了大量的插入和更新,并经常删除所有条目,并且只定期进行一些选择,那么没有任何索引可能会更快。然而,这将是一个相当特殊的情况,所以你必须做一些基准测试,并决定它是否在你的具体情况下有意义。
答案 2 :(得分:0)
好问题。我想补充一下@hexist已经提到过的内容以及@ ypercube链接提供的信息。
按照设计,数据库不知道表的哪个部分会找到满足提供的predicates的数据。因此,DB将对所有表的数据执行完整或顺序扫描,过滤所需的行。
索引是一种特殊的数据结构,对于给定的key
,可以精确指定将在哪些行中找到这样的值。涉及索引时的主要区别:
使用索引将导致随机IO模式,与完整扫描中使用的顺序模式相比。您可以谷歌搜索随机和顺序磁盘访问的比较数字,但它可能会有一个数量级的差异(当然随机速度较慢)。
但是,很明显,在某些情况下,索引访问将更便宜,而在其他情况下,应首选全扫描。这取决于指定谓词将返回多少行(总共),或者它的选择性:
I need address information for customer with internal number = XXX
; I need 20 most recent purchases for each of the top 5 categories by number of goods
。DB如何决定做什么,索引还是全扫描?这是运行时决策,它基于统计信息,因此请务必保持最新状态。实际上,上面提供的数字没有实际值,您必须独立评估每个查询。
所有这些都是对所发生情况的粗略描述。我非常建议调查How PostgreSQL Planner Uses Statistics,这是我在这个问题上看到的最好的。