HashCrack程序数据及索引设计

原创 2010年05月31日 01:52:00

 

前文已经讲述,字母全排列是个惊人的数字,即使只遍历小写字母和数字6个全排列也有36^6 = 217678233621亿多个,7个排列36^7 = 78364164096783亿多,8个排列36^8 = 28211099074562.8万亿多个,数字非常惊人。Md5反查是个string-string的映射,16-N个字符的映射,如果考虑hex模式的md5那就是32-N的映射,考虑映射人们最先想到的可能都是数据库存储方式,我也首先想到了用数据库存储,分别考察了一下sqliteberkeleydb,但测试下来制造数据的速度很慢,sqlite加索引大概只能到5w条记录/s,不加索引为10w/sberkeleydb用单条模式大概只能到4.5w/s,这个速度已经很慢了,更难于接受的是如果写1000wsqlite加索引来说不是耗时200s,而是2000s了,也就是说耗时随单个数据文件记录的条数增多几乎成平方模式递增,而不是简单的线性递增,这是很要命的,就算制造1亿条数据耗时也是惊人,我的实测中没有测试过用sqlite制造1000w条以上的数据,在我心目中已经否定了那种模式。虽然我知道很多号称有多少亿条数据的网站其实都是用的数据库,我不知道他们花了多少时间制造数据,或者几天,或者几个月,或者更长时间,反正我对采用普通数据库模式制造数据完全持否定态度,嵌入式速度太慢,其他数据库则不光速度慢而且也不适合分布式应用,难道用户每装个点还要装个mysql之类的数据库,几乎不可能啊。

下面说说我的方法,我本来第一版本是计划先不做文件式数据库的,第一版本来只规划了做内存数据,充分榨取每一个字节,关于内存数据库我实现了好几个版本,下面分别介绍一下:

版本1hash模式

char key[16];做键,char pass[n];做内容,由于hash桶占用了一些字节:

                DWORD h, nKeyLen;               //hash键值, 字符串长度

                DWORD tag;                           //私有值,默认为0提供给外部使用

                bucket *pListNext;           //hash表双链的下一个节点

                bucket *pListPrev;           //hash表双链的上一个节点

                bucket *pNext;                        //拉链的下一个节点

                VALUE second;                        //具体数据

                _Elem first[0];                 //first

用这个hash模式大概存储一个6个字符的串的md5信息花了50个字节,花费太多,结果自然存不了多少数据,该方案作为第一验证方案,除了花费内存太多还是个能通过的方案。

 

版本2hash简化方案

在上述版本基础上简化桶设计,抛弃作为标准桶的一些字段,精简之后如下:

                DWORD h;                               //hash键值

                bucket *pNext;                        //拉链的下一个节点

                byte nKeyLen;                  //字符串长度

                VALUE second;                        //具体数据

                _Elem first[0];                 //first

该版本存储一个6个字符的串的md5信息需要31个字节,比版本1少了很多,进步一些了。

方案1和方案2速度都很快。

 

版本3vector方案

考虑到hash占用内存较多,采用vector方案,直接存储

Char mm[16];

Char pass[n];

存储一个6个字符的串的md5信息需要22个字节,该方案排序速度太慢,查找速度肯定也比不上版本1和版本2,之后还测试过将vector里面存储指针,那种模式每个6个字符的串的md5信息占用内存26个,接近hash版本,排序速度比直接存储数据的好一点,但也还是很慢,总之这个方案作为一个过度方案最终也被放弃了。

 

 

方案4:全文件Hash紧缩方案

以上这些方案的特点是都存储了char mm[16]; 也就是说存储部分都有计算出来的md5,经过思考之后觉得可以放弃存储md5,不存储md5是个很妙的想法,继续发挥hash思想,也不保存根据md5计算出来的hash值本身,只将该md5和串的信息关联到hash值的模所在的索引节点,这样就将索引节点信息减少到极致:

        size_t coffset;                  //content offset low

        unsigned short a:12;       //切分为12, 4

        unsigned short b:4;         //4,为下一个冲突值的索引序数,如果没有就为0

        size_t nextindex;             //冲突条目的存储序号,为0表示没有冲突

 

使用该索引可让单文件最多支持内容16T,最多687亿记录,具体实现的时候由于全使用文件所以速度比较慢,速度退化到sqlite之类同一级别了,不过这个设计思想为方案5提供了借鉴,如果跟方案5一样用大块内存辅助,速度大概可以上升一个级别,不过由于没有具体实现,待研究之后再做评估。

 

方案5hash紧缩内存方案

学习方案4的设计思想,考虑仅在内存里面实现一个紧凑型文件,由于只考虑内存可表示的32位范围,所以简化索引节点定义如下:

Size_t coffset;          pass相对于内容区首的偏移

Size_t nindex;          冲突节点下一个序,如果为0则表示没有冲突

内容区存储更简单,每个字符串直接保存,最后的0也保存,这样每个字符串自然分开,对一个6个字符长的串来说,保存一个信息只需要15个字节,真的是省啊,1亿个字符串也只要大约1.5g左右硬盘就够了。此方案虽然很妙,但实现的时候却费了一些周折,具体做的时候也做过好几个版本,由于考虑该方案的内容和索引最后都可以直接保存到文件,所以该方案对位置的保存都用的是相对位置,也由于想让索引节点信息简单,最初是让冲突索引采用线性步长跳跃方法,测试之后发现这个方法速度奇慢,而且还有个非常讨厌的问题,随着数据量的增多冲突扩散越来越厉害,耗时非线性的陡峭增长。放弃这个实现之后还是回到了经典的拉链法,拉链法速度就是快,但拉链法处理索引节点虽然容易,但要让索引信息可直接保存却要花一些脑子,最后采用先用内存扩展拉链,待全部索引构造好之后再把拉链出来的部分重新填到原始索引区中的空区,并修正对应索引相对位置。这个方法的精妙之处在于既省空间又有速度,最令人兴奋的是采用该方法耗时随着数据量的增大是线性增长,最后的实现在我的笔记本上大概100w/s1亿条记录从字母组合到最终生成索引文件也只要不到2分钟的时间,制造了一些数据之后统计了一下,冲突节点比例大概占26%-35%,也就是说有65%以上的数据只要一次hash就直接命中,平均拉链长度1.2左右,最长拉链10,总体还是很满意的。

 

原本第一版没有考虑这个可存储的方案,但花了几天就搞定了一个基本可用的存储方案还是很令人兴奋的,虽然该存储方案还有一些问题没有彻底解决,但已经有进一步处理的办法,待下一个相对空闲时间段再仔细研究一下,定会有更简洁的实现做出来,至于待解决的是什么问题以及如何解决那些问题还是等我代码写好了再写出来吧。

 

 

 

SQL Server 2014 索引和游标

主讲内容: 第一讲 课程简介 第二讲 索引简介 第三讲 创建索引 第四讲 查看索引 第五讲 索引管理 第六讲 全文索引 等课程
  • 2017年01月19日 11:00

HashCrack程序数据及索引设计2

HashCrack程序数据及索引设计2  上个月写了《HashCrack程序数据及索引设计》里面已经提到早期设计的几种存储方法,最后达到了每条记录15个字节左右的水平,但这个存储效果还是很差的,而且是...
  • oldworm
  • oldworm
  • 2010-06-30 14:12:00
  • 651

HashCrack程序规划

HashCrack程序规划 最近几天在思考如何遍历md5找出原码字符串,但九十多个可见字符,96^6 782757789696,就算只遍历6位组合也是非常惊人的巨量数据,单机根本无法完成,根据常用密码...
  • oldworm
  • oldworm
  • 2010-05-24 11:20:00
  • 753

数据库中索引的策略和设计

MySQL5.0中索引的设计和使用     下面讨论下MySQL5.0中的索引的设计和使用。任何东西设计的好,那么使用起来就顺手。不过很多时候给出设计什么规则这些都是相对的。做任何的事情,最重要...
  • cs408
  • cs408
  • 2015-10-07 16:48:58
  • 328

《数据库索引设计优化》读书笔记(三)

《数据库索引设计优化》读书笔记(三) 第6章 影响索引设计过程的因素 练习 6.1 图6.5中的SELECT查询在当前索引条件下需要花费1分钟。请用两种方案设计可能的最佳索引:(1)不增加额外的第三...
  • wzy0623
  • wzy0623
  • 2016-02-02 10:41:55
  • 1248

《数据库索引设计优化》读书笔记(一)

第3章 SQL处理过程 练习 3.1 为SQL3.7中所示的查询设计尽可能好的索引: -- SQL 3.7 SELECT LNAME, FNAME, CNO FROM CUST WHE...
  • wzy0623
  • wzy0623
  • 2016-02-01 14:56:14
  • 2253

索引设计规范原则

1.1.1. 引设计原则 1.原则上表索引的个数不能超过5个; 2.原则上单个字段上的索引不能超过2个; 3.原则上复合索引引用的字段不能超过3个字段; 4.原则上分区表的索引类型全部使用LO...
  • u013322876
  • u013322876
  • 2016-11-01 10:38:32
  • 1323

网站设计UI及优秀设计网址大全

  • 2015年08月25日 16:33
  • 56KB
  • 下载

HBase二级索引的设计(案例讲解)

摘要 最近做的一个项目涉及到了多条件的组合查询,数据存储用的是HBase,恰恰HBase对于这种场景的查询特别不给力,一般HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在R...
  • liyong1115
  • liyong1115
  • 2017-04-21 16:31:17
  • 956

mysql设计索引的原则与索引的选择

索引是提升数据库性能最直接的手段,如果没有索引,mysql必须从第1条记录开始然后读完整个表直到找出相关的行.表越大花费的时间越多.           mysql中的MyISAM和InnoDB存储...
  • fly_zhyu
  • fly_zhyu
  • 2017-06-21 11:26:24
  • 375
收藏助手
不良信息举报
您举报文章:HashCrack程序数据及索引设计
举报原因:
原因补充:

(最多只允许输入30个字)