第十三 C#中的bitmap运算
在我们日常工作中,有时候可能遇到大数据的查询判断是否存在,比如前段时间我遇到的一个优化问题,1.2亿数据中判断用户id是否存在,
如果在数据库建立索引,而且用UserId做集聚索引的话,查询速度还可以,但是如果是大并发查询怎么办,每次查询链接和打开数据库是很耗费资源的,这个时候我们要怎么做
,当时想到放到redis里面,这个的确可以,而且数据很快,但是放到redis里面同样有网络IO,而且1.2亿数据放到redis中,占用的空间也不小,
这个时候就想到了bitmap的位运算(原理就不详细说了),用数组的bit位来标识数据是否存在,大家知道一个 long是64位,那我们就可以表示64个基本数据,每一位,存在的话设置为1,不存在的话就是0,
下面是我用long数组实现的一个bitmap,测试了一下,1.2亿数据,占用内存是24M,比redis小了很多,而且没有网络IO的开销,速度很快,
而且这样做成了位,我们在做比较比如交集,并集也很方便
---
/// <summary>
/// BitMap数据处理类
/// </summary>
public class MyBitMap
{
/// <summary>
/// 文档大小
/// </summary>
private int size;
private long[] words;
/// <summary>
/// 初始化BitMap
/// </summary>
/// <param name="size"></param>
public MyBitMap(int size)
{
this.size = size;
this.words = new long[GetWordIndex(size - 1) + 1];
}
/// <summary>
/// 添加数据
/// </summary>
/// <param name="bitindex"></param>
public void AddWord(int bitindex)
{
if(bitindex<0 || bitindex>this.size-1)
{
return;
}
int wordIndex = GetWordIndex(bitindex);
this.words[wordIndex] |= (1L << bitindex);
}
/// <summary>
/// 获取一个数据是否在BitMap中
/// </summary>
/// <param name="bitindex"></param>
/// <returns></returns>
public bool GetWordIsTrue(int bitindex)
{
if (bitindex<0 || bitindex>this.size-1)
{
return false;
}
int wordIndex = GetWordIndex(bitindex);
return (this.words[wordIndex] & (1L << bitindex)) != 0;
}
/// <summary>
/// 把一个数据从bitmap中清理掉
/// </summary>
/// <param name="bitindex"></param>
public void ClearWord(int bitindex)
{
if(bitindex<0 || bitindex>this.size-1)
{
return;
}
int wordIndex = GetWordIndex(bitindex);
this.words[wordIndex] ^= (1L << bitindex);
}
/// <summary>
/// 获取一个数字在word中的位置
/// </summary>
/// <param name="bitindex"></param>
/// <returns></returns>
private int GetWordIndex(int bitindex)
{
return bitindex >> 6;
}
}