字符串列上的postgresql索引

Posted

技术标签:

【中文标题】字符串列上的postgresql索引【英文标题】:postgresql index on string column 【发布时间】:2013-05-31 05:34:15 【问题描述】:

比如说,我有一个表ResidentInfo,在这个表中我有唯一的约束HomeAddress,也就是VARCHAR 类型。为了将来的查询,我将在此列上添加一个索引。 查询只会有操作=,我会使用B-TREE模式,因为目前不推荐使用Hash模式。

问题:从效率的角度来看,使用B-TREE,你认为我应该添加一个新的列,编号为1,2,3....,N 对应不同的家庭地址,而不是在HomeAddress上添加索引,我应该在数字列上添加索引吗?

我问这个问题是因为我不知道索引是如何工作的。

【问题讨论】:

感谢@Denis 指出唯一约束会自动建立索引。 根据性能有一个始终适用的准则:测试它。从这种模糊的描述中获取所有用例是不可能的,所以当你询问速度时,测试什么对你来说是最快的。在某些情况下,理论上次优方法对于您通常处理的数据更快。 【参考方案1】:

对于简单的相等检查 (=),varchartext 列上的 B-Tree 索引很简单,也是最佳选择。它确实有助于提高性能很多

当然,简单的integer 上的 B-Tree 索引性能更好。对于初学者来说,比较简单的integer 值要快一些。但更重要的是,性能也是索引大小的函数。更大的列意味着每个数据页的行数更少,意味着需要读取更多的页面......

由于HomeAddress 无论如何都不是唯一的,它不是一个好的自然主键。我强烈建议改用 代理主键serial column 是显而易见的选择。它的唯一目的是使用一个简单、快速的主键。

如果您有其他表引用该表,这将变得更加有效。而不是为外键列复制一个冗长的字符串,您只需要一个整数列的 4 个字节。而且您不需要进行如此多的级联更新,因为地址必然会发生变化,而代理 pk 可以保持不变(但当然不是必须)。

您的表格可能如下所示:

CREATE TABLE resident (
   resident_id serial PRIMARY KEY
  ,address text NOT NULL
   -- more columns
);

CREATE INDEX resident_adr_idx ON resident(address);

这会产生两个 B-Tree 索引。 resident_id 上的唯一索引和 address 上的普通索引。

More about indexes in the manual. Postgres 提供了很多选项 - 但对于这个简单的案例,您不再需要了。

【讨论】:

非常感谢!这真的很有帮助!因此,这两个 B-Tree 索引将加快诸如“SELECT * FROM resident WHERE resident_id=xxxxx;”之类的查询。如果我必须使用地址查询,也给我一个选项,对吗? @Hao:正确。此外,这两个索引都支持的不仅仅是简单的相等检查。 谢谢!正如你所说,关于B-TREE的操作,EnterpriseDB的Hash Pattern Index现在仍然存在缺陷,一旦他们修复它我可能会切换到Hash Pattern,因为我只是使用“=”操作进行查询。 Hash 采用 O(1),B-Tree 采用 O(nlogn)。【参考方案2】:

在 Postgres 中,通过在字段上维护唯一索引来强制执行唯一约束,因此您已经被覆盖了。

如果您认为对地址的唯一性约束不好(老实说,它是:什么配偶创建一个单独的帐户?关于公寓?等等),您可以像这样创建一个:

create index on ResidentInfo (HomeAddress);

【讨论】:

哦,感谢您指出这一点!但问题仍然存在。如果我添加一个数字列并使用它而不是地址,查询会变得更快吗?

以上是关于字符串列上的postgresql索引的主要内容,如果未能解决你的问题,请参考以下文章

将具有日期和纪元格式值的字符串列转换为 postgresql/Tableau prep 中的日期列

连接字符串列和索引

Apache Spark:尝试索引字符串列时出现 ***Error

使用负索引从pyspark字符串列的最后一个索引中对多个字符进行子字符串

PostgreSQL 上所有列的索引

PostgreSQL 11 对索引应该足够的分区表进行并行 seq 扫描