我使用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>';
答案 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列较小的数据,则可以创建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
找出你的索引是否被使用的最好方法是使用“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(),并且需要添加完整的数据比较以解决可能的哈希冲突。
还有另一种可能性。单列索引可以帮助您减少索引行大小,而不是多列组合索引。