基本数据库
没什么好说的,建表、查表。
哈希表
一般来说,哈希表的时间复杂度是常数级别。
数据量较少时,哈希表也许是个不错的选择,但是面对亿级别的数据量,哈希表的哈希冲突和内存消耗是个问题。假设哈希表的每个 key 和 value 占用10字节,1亿条数据大约占用 1G,对于现代计算机来说,1G其实不算大,但是有没有更好的方案呢?
优化哈希表 - 布隆过滤器
为了减少内存,引入bitMap数据结构。可以预先分配bit类型的数组,数组的大小是最大数据量的一个倍数。假设系统的最大数据量为1亿,定义一个长度为5亿的bit数组。选择一个哈希冲突比较小的哈希函数计算每一个数据的哈希值,并设置bit数组相应哈希值位置的值为1。为了避免哈希冲突,我们用多个不同的哈希函数来计算同一个数据,来产生不同的哈希值,同时把这多个哈希值对应的数组位置都置为1。刚才新建的数组为最大数据量的一个倍数也是为了减小冲突的一种方式(容量越大,冲突越小)。当一个1亿条数据量级,5亿的bit数组占用内存才几百M而已,比哈希表要小很多,在10亿级别下内存占用差距将会更大。
以下为Java代码示例:
class BloomFilter
{
public BitMap arr = null;
public BloomFilter(int len)
{
arr = new BitMap(len);
}
public void Set(string key)
{
var idx1 = Hash1(key);
var idx2 = Hash2(key);
var idx3 = Hash3(key);
var idx4 = Hash4(key);
arr [idx1] = true;
arr [idx2] = true;
arr [idx3] = true;
arr [idx4] = true;
}
public bool Get(string key)
{
var idx1 = Hash1(key);
var idx2 = Hash2(key);
var idx3 = Hash3(key);
var idx4 = Hash4(key);
return arr [idx1] && arr [idx2] && arr [idx3] && arr [idx4];
}
//哈希函数
int Hash1(string key)
{
int hash = 5381;
int i;
int count;
char[] bitmap= key.ToCharArray();
count = bitmap.Length;
while (count > 0)
{
hash += (hash << 5) + (bitmap[bitmap.Length - count]);
count--;
}
return (hash & 0x7FFFFFFF) % arr .Length;
}
int Hash2(string key)
{
int seed = 131; // 31 131 1313 13131 131313 etc..
int hash = 0;
int count;
char[] bitmap= (key+"key2").ToCharArray();
count = bitmap.Length;
while (count > 0)
{
hash = hash * seed + (bitmap[bitmap.Length - count]);
count--;
}
return (hash & 0x7FFFFFFF)% arr .Length;
}
int Hash3(string key)
{
int hash = 0;
int i;
int count;
char[] bitmap= (key + "keykey3").ToCharArray();
count = bitmap.Length;
for (i = 0; i < count; i++)
{
if ((i & 1) == 0)
{
hash ^= ((hash << 7) ^ (bitmap[i]) ^ (hash >> 3));
}
else
{
hash ^= (~((hash << 11) ^ (bitmap[i]) ^ (hash >> 5)));
}
count--;
}
return (hash & 0x7FFFFFFF) % arr .Length;
}
int Hash4(string key)
{
int hash = 5381;
int i;
int count;
char[] bitmap= (key + "keykeyke4").ToCharArray();
count = bitmap.Length;
while (count > 0)
{
hash += (hash << 5) + (bitmap[bitmap.Length - count]);
count--;
}
return (hash & 0x7FFFFFFF) % arr .Length;
}
}