假设我们有一张桌子A(id int primary key, a varchar(32), b varchar(32), ..., z varchar(32))。
我经常运行一个查询:
select count(*) from A where a = :a and b = :b
一个合理的解决方案是在字段上使用覆盖索引,index (a, b)以便没有不必要的数据访问。
- 添加到它是否有意义
id,是index(a, b, id)吗? - 在使用查询的情况下会有所帮助吗:
select count(*) from A where a = :a和select count(*) from A where b = :b. 或者是否有必要在字段上创建单独的索引:index(a)和index(b)?
Postgresql 数据库(虽然我不认为这应该有效果)。
这对于任何性能问题都是至关重要的。
postgresql 中的索引存储对数据文件中行的物理地址的引用 -
TID. 因此,主键的值无关紧要,将主键的字段包含在索引中而不需要它甚至会变得更糟——索引会占用更多的空间,这意味着更多的数据将读取和写入磁盘,shared_buffers 和页面缓存系统将占用更多内存。取决于索引类型。第一个问题的答案是肯定的,对于实际的基础版本可以是抽象的。对于不同类型的索引,必须分别考虑第二个问题的答案。
btree是通常的意思,也是create index. 它是一棵树,如果你不能从它的根开始,你就不能正确地搜索这棵树。因此,它btree(a,b)可以加快对 a 的条件的查询,但对于仅在 b 上的条件,它的效率会很低——您将不得不查看整个索引而不是它的一部分。brin- 这种类型的索引不关心参与字段的顺序。brin(a,b)可用于a = ?两者b = ?hash- 好吧,这样更容易,它只是不知道如何使用多列索引。gin/gist有点离题,本身不支持简单类型。btree_gin已经可以使用/ extensions构建btree_gist,但总的来说 gist 和 gin 是单独的文章的好主题。还有两个重要的点:
btree是覆盖索引btree也不能保证表格不会被阅读。相反,它只能保证这张表的某些块可能不必被读取。这个看似奇怪的画面是通过 MVCC 机制的实现来解释的。索引仅存储数据和对行的引用,但不存储有关该行的事务可见性的数据。因此,必须检查索引搜索结果的每一行,以查看该行是否对当前事务可见。
index only scan实现的本质postgresql是能够跳过事务可见性检查(而不是从表中读取数据块),如果该块具有为visibility map. 该位图autovacuum要么是手动更新vacuum的,因此是需要将 autovacuum 配置为更密集地工作以使 postgresql 正常工作的另一个原因。开箱即用的配置 - 不是为了工作,而是为了在任何地方运行而不会打扰任何人。如果可见性图没有说该块对每个人都是可见的,那么数据库需要读取表的这一部分并检查必要的行。对于积极更新和高度相关的数据,拥有覆盖索引可能根本没有意义。
count但是对于 MVCC 基础来说,这通常是一件非常不方便的事情。对您来说,这是一个简单的数字,用于基础 - 分别检查该行的每个版本,是否对您可见。查询中的 id 只有在添加到索引时才会受到伤害。在第二点上,您需要创建单独的索引。