数据库索引空间优化-散列算法

        create unique index on urls using btree(decode(md5(url), 'hex'));

       select * from urls where decode(md5(url), 'hex') = decode(md5({输入的URL串}), 'hex');
     
        通常需要对一些长文本字段建立唯一索引,比如,我们自己的应用里面,经常会有 URL 或者 URI 字段,里面保存类似:
       http://www.pgsqldb.org/mwiki/index.php
       这样的数据,并且要求唯一、不重复,常见的做法是创建一个唯一索引:
       ,但是如果只是做唯一的用途的话,会产生相当大的索引,比如我们有个表的索引就达到了 2.4G bytes 的大小,
       我们可以对URL做MD5运算,算出其散列值,只要散列值唯一,就基本可以保证URL是唯一的。(注意:我知道MD5是可能碰撞的,不过我们自己的数据量恐怕没那么容易碰撞,所以,先相信之)。于是,我可以创建这么一个索引:

  create unique index on urls using btree(md5(url));
  
  2.4G缩小到了900M多,貌似还可以,但是是不是就真的OK了?非也。

仔细看看 postgresql 里头 md5()函数的定义,它返回的是 text 类型,也就是用hex转码后的文本流,其宽度是 32 bytes,其实也不小!而我们只要二进制数据就可以了,所以,我们还要继续优化!

仔细查阅文档,可以发现 decode() 可以把 hex 转码的文本流反转成二进制类型(bytea),所以,我们这么干:

  create unique index on urls using btree(decode(md5(url), 'hex'));
就可以实现md5的二进制上头的唯一索引,现在看看大小:475M!老天,我们节约了 2G 的空间(内存)!

这个时候,我们需要用下面的方法查询URL或者URI是否存在:

  select * from urls where decode(md5(url), 'hex') = decode(md5({输入的URL串}), 'hex');

 create unique index on urls using btree (url);
  后记
二进制 16 字节的散列算法可能还是有些杀鸡用牛刀了,因为一般我们的数据也就几千万上亿行,所以64位(8字节)的散列算法就挺好的了,这个时候,我们可以考虑使用一些外部包,比如看看贡献包Pgcrypto的digest函数,digest自身也支持md5,用法是:

 select digest(url, 'md5')
也支持sha等,担心MD5碰撞的朋友,可以使用这个贡献包的sha算法。

也可以找FNV算法来实现64位(8字节)的散列,这样前面475M的索引,在付出一定的碰撞概率增大的风险之后,有可能进一步缩小到290M左右!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值