即使在创建索引时,postgres的性能也会降低

时间:2013-10-15 23:49:27

标签: sql postgresql

我使用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>';

3 个答案:

答案 0 :(得分: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的值,因为只有col3的md5存储在那里,因此它仍然需要转到表中以获取col3

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

现在,如果col3是其中包含大量数据并且第1列和第2列较小的数据,则可以创建col1col2的正常索引。您实际上只需要为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

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

为每列创建索引,而不是组合列。如果为多个分隔列创建索引,postgresql查询平面可以使用它所谓的位图索引扫描来组合它们。组合单列索引通常速度很快,您可以在引用索引列的任何查询中使用它们。为组合列创建索引并不是一个好的设计。

参考Postgresql doc 11.5. Combining Multiple Indexes

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

还有另一种可能性。单列索引可以帮助您减少索引行大小,而不是多列组合索引。