4

我使用 md5 在 postgres 中为下面提到的表创建了索引。索引和表格如下:

 create table my_table(col1 character varying, col2 character varying, col3 character varying);

my_table 看起来像(我刚刚给出了一个例子。我的实际表是 1Tera Byte):

   col1  col2   col3
   <a12> <j178> <k109>

create index index1 on my_table (md5(col1), md5(col2), md5(col2));

我试图在不使用 md5 的情况下创建索引,但是我最终得到了错误:

ERROR:  index row size 2760 exceeds maximum 2712 for index "index1"
HINT:  Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.

但是,我注意到无论我是否创建了索引,我的查询处理时间都保持不变。我很困惑可能是什么原因。有人可以帮我吗?

我触发的 sql 查询的形式为:

select col3 from my_table where col1='<a12>' and col2='<j178>';
4

3 回答 3

6

由于在尝试创建标准 btree 索引时遇到错误,我猜测这些列中的一个或多个列中的数据非常大。

您创建的索引可能最好描述为“三列 md5 哈希的 b 树索引”,而不是“三列 md5 索引”。

为了让 PostgreSQL 使用索引,您的查询必须针对 md5 哈希。尝试:

SELECT col3
FROM my_table 
WHERE
      md5(col1) = md5('<a12>')
  and md5(col2) = md5('<j178>')

计划者会说“哦,我有一个 md5(col1) 等的索引,我会使用它”。请注意,这仅适用于完全相等查询 (=),不适用于 LIKE 或范围查询。它也不会col3从索引中获取值,因为只有 md5col3存储在那里,所以它仍然需要去表中获取col3值。

对于一个小表,这可能会导致规划器决定跳过索引并只对表进行完整扫描,但听起来你的表足够大以至于索引是值得的 - postgres 将扫描索引,找到匹配的行条目,然后从表中检索这些行。

现在,如果col3是其中包含大量数据且列 1 和 2 很小的列,则您可以创建一个col1,的普通索引col2。您实际上只需要索引where子句中的列,而不是select部分中的列。

postgres 索引文档非常好:http ://www.postgresql.org/docs/9.0/static/indexes.html但 CREATE INDEX 页面可能是最有用的一个:http ://www.postgresql.org/ docs/9.1/static/sql-createindex.html

找出是否正在使用您的索引的最佳方法是使用“解释”指令:http ://www.postgresql.org/docs/9.1/static/sql-explain.html - 如果您使用 pgadmin3 来玩您的数据库(我强烈推荐它)然后只需在查询窗口中按 F7,它就会进行解释并将其显示在一个漂亮的 GUI 中,向您显示查询计划。这节省了很多小时试图找出我的索引没有被使用的原因。

于 2013-10-16T00:28:16.333 回答
1

为每列创建索引,而不是合并列。如果您为几个单独的列创建索引,postgresql 查询平面可以使用它所谓的位图索引扫描来组合这些。组合单列索引通常同样快,您可以在任何引用您索引的列的查询中使用它们。为组合列创建索引不是好的设计。

参考Postgresql 文档 11.5。组合多个索引

关于 md5,我在没有您刷新的情况下发布了。使用 md5() 是可以的。与其他答案一样,您还应该在 where 子句中使用 md5() 并且需要添加完整的数据比较以解决可能的哈希冲突。

还有另一种可能。与多列组合索引相比,单列索引可以帮助您减少索引行大小。

于 2013-10-15T23:58:05.653 回答
1

为什么在创建索引时应用 MD5?您可以通过存储感兴趣列的 MD5 值来利用 HASH 索引,并在该列上创建 HASH 索引,并按该哈希值进行搜索。但我认为你不需要所有这些。

我看到您正在创建 B-TREE 索引,您应该只使用常规列,而不使用任何哈希加密。当您在 Where 子句中使用直接运算符时,B-TREE 索引的性能最佳。

于 2013-10-16T00:06:35.170 回答