字符串列上的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】:对于简单的相等检查 (=
),varchar
或 text
列上的 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