Skip to content
muyannian edited this page Mar 15, 2013 · 15 revisions

1.将每个值转换为整形,目前是通过crc32,但目的是能将数据打散的均匀。
2.将crc32的值进行抽样,存储到hashset中。
3.使用局部的haseset来估算整体。

下面为海狗中的使用示例

最基本的使用 
./bluewhale higo sql "\" select count(empty_l),dist(alipay_direct_amt),dist(is_3c) from rpt_p4padhoc_cust where thedate range '20130201,20130220'  limit 0,40 \""
Running:  select count(empty_l),dist(alipay_direct_amt),dist(is_3c) from rpt_p4padhoc_cust where thedate range '20130201,20130220'  limit 0,40 
totalRecords:1
count(empty_l)  dist(alipay_direct_amt) dist(is_3c)
***24374        148224.0        2.0
times taken 4 seconds

来个复杂点的

bash-3.2$ ./bluewhale higo sql "\" select thedate,count(empty_l),dist(alipay_direct_amt),dist(is_3c) from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by thedate limit 0,40 \""
Running:  select thedate,count(empty_l),dist(alipay_direct_amt),dist(is_3c) from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by thedate limit 0,40 
totalRecords:20
thedate count(empty_l)  dist(alipay_direct_amt) dist(is_3c)
20130201        **54258 *6*36.0 2.0
20130202        **54506 *2*37.0 2.0
20130203        **54678 *9*56.0 2.0
20130204        **54843 *6*46.0 2.0
20130205        **55023 *3*00.0 2.0
20130206        **55166 *0*99.0 2.0
20130207        **55297 *5*9.0  2.0
20130208        **55415 *8*7.0  2.0
20130209        **55474 *2*6.0  2.0
20130210        **55551 *9*0.0  2.0
20130211        **55655 *0*3.0  2.0
20130212        **55809 *5*0.0  2.0
20130213        **55997 *1*56.0 2.0
20130214        **56145 *5*83.0 2.0
20130215        **56368 *8*82.0 2.0
20130216        **56737 *5*78.0 2.0
20130217        **57801 *8*01.0 2.0
20130218        **58805 *3*12.0 2.0
20130219        **59845 *4*74.0 2.0
20130220        1361001 *8*93.0 2.0
times taken 2 seconds


 按照省的
bash-3.2$ ./bluewhale higo sql "\" select prov,count(empty_l),dist(alipay_direct_amt),dist(prov),dist(city) from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by prov limit 0,40 \""
Running:  select prov,count(empty_l),dist(alipay_direct_amt),dist(prov),dist(city) from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by prov limit 0,40 
totalRecords:36
prov    count(empty_l)  dist(alipay_direct_amt) dist(prov)      dist(city)
_       *77**0  *55.0   1.0     1.0
上海    *19**77 *3400.0 1.0     1.0
云南省  *22**1  *420.0  1.0     16.0
内蒙古自治区    *0257   956.0   1.0     12.0
北京    **33323 *8675.0 1.0     1.0
台湾省  **34    *6.0    1.0     22.0
吉林省  **023   *865.0  1.0     9.0
四川省  **4638  *812.0  1.0     21.0
天津    **3930  *060.0  1.0     1.0
宁夏回族自治区  *1830   242.0   1.0     5.0
安徽省  **6278  *320.0  1.0     17.0
山东省  **0588  *4635.0 1.0     17.0
山西省  **536   *044.0  1.0     11.0
广东省  **04653 *4576.0 1.0     21.0
广西壮族自治区  **6561  *529.0  1.0     14.0
新疆维吾尔自治区        *5886   881.0   1.0     18.0
江苏省  **04074 *9993.0 1.0     13.0
江西省  **7868  *096.0  1.0     11.0
河北省  **8196  *480.0  1.0     11.0
河南省  **1900  *316.0  1.0     18.0
浙江省  **67889 *3800.0 1.0     11.0
海南省  **504   *68.0   1.0     20.0
海外    **311   *335.0  1.0     1.0
湖北省  **2981  *796.0  1.0     17.0
湖南省  **7559  *883.0  1.0     14.0
澳门特别行政区  *267    34.0    1.0     2.0
甘肃省  **847   *22.0   1.0     14.0
福建省  **69715 *9638.0 1.0     9.0
西藏自治区      *765    115.0   1.0     7.0
贵州省  **567   *43.0   1.0     9.0
辽宁省  **0806  *416.0  1.0     14.0
重庆    **9921  *824.0  1.0     1.0
陕西省  **0812  *496.0  1.0     10.0
青海省  **83    *16.0   1.0     8.0
香港特别行政区  *986    55.0    1.0     3.0
黑龙江省        *07418  1541.0  1.0     13.0
times taken 3 seconds 


在来个复杂点的 

./bluewhale higo sql "\" select prov,count(empty_l) as cnt,dist(custid) as cid,dist(prov) as pro,dist(city) as city from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by prov order by city desc limit 0,40 \""
Running:  select prov,count(empty_l) as cnt,dist(custid) as cid,dist(prov) as pro,dist(city) as city from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by prov order by city desc limit 0,40 
totalRecords:36
prov    cnt     cid     pro     city
台湾省  *534    *35.0   1.0     22.0
四川省  *44638  *5124.0 1.0     21.0
广东省  *104653 *54304.0        1.0     21.0
海南省  *9504   *955.0  1.0     20.0
新疆维吾尔自治区        45886   2401.0  1.0     18.0
河南省  *31900  *6568.0 1.0     18.0
安徽省  *66278  *7625.0 1.0     17.0
山东省  *90588  *5152.0 1.0     17.0
湖北省  *52981  *7164.0 1.0     17.0
云南省  *22941  *260.0  1.0     16.0
广西壮族自治区  *96561  9624.0  1.0     14.0
湖南省  *37559  *9664.0 1.0     14.0
甘肃省  *6847   *560.0  1.0     14.0
辽宁省  *00806  *5448.0 1.0     14.0
江苏省  *404074 *17504.0        1.0     13.0
黑龙江省        *07418  5812.0  1.0     13.0
内蒙古自治区    *0257   2626.0  1.0     12.0
山西省  *7536   *896.0  1.0     11.0
江西省  *77868  *3307.0 1.0     11.0
河北省  *88196  *2272.0 1.0     11.0
浙江省  *867889 *33472.0        1.0     11.0
陕西省  *40812  *332.0  1.0     10.0
吉林省  *6023   *532.0  1.0     9.0
福建省  *669715 *2160.0 1.0     9.0
贵州省  *5567   *097.0  1.0     9.0
青海省  *283    *36.0   1.0     8.0
西藏自治区      *765    256.0   1.0     7.0
宁夏回族自治区  *1830   624.0   1.0     5.0
香港特别行政区  *986    359.0   1.0     3.0
澳门特别行政区  *267    67.0    1.0     2.0
_       *77450  *1576.0 1.0     1.0
上海    *198277 *06688.0        1.0     1.0
北京    *633323 *2016.0 1.0     1.0
天津    *83930  *964.0  1.0     1.0
海外    *9311   *849.0  1.0     1.0
重庆    *59921  *888.0  1.0     1.0
times taken 5 seconds 

多个列的情形 
./bluewhale higo sql "\" select prov,city,count(empty_l) as cnt,dist(custid) as cid from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by prov,city order by cid desc limit 0,40 \""
Running:  select prov,city,count(empty_l) as cnt,dist(custid) as cid from rpt_p4padhoc_cust where thedate range '20130201,20130220' group by prov,city order by cid desc limit 0,40 
totalRecords:393
prov    city    cnt     cid
广东省  广州市  *116213 *49312.0
上海    上海市  *198277 *06688.0
广东省  深圳市  *966038 *6768.0
北京    北京市  *633323 *2016.0
浙江省  杭州市  *632057 *7792.0
浙江省  金华市  *008819 *3504.0
_       _       *77450  *1576.0
江苏省  苏州市  *42152  *4169.0
福建省  泉州市  *54617  *1265.0
浙江省  嘉兴市  *95311  *8225.0
广东省  东莞市  *81284  *7686.0
浙江省  温州市  *19859  *3630.0
福建省  莆田市  *15188  *1448.0
四川省  成都市  *07932  *9390.0
湖北省  武汉市  *78516  *8516.0
广东省  佛山市  *57025  *8486.0
湖南省  郴州市  *42621  *8188.0
浙江省  台州市  *80656  *7284.0
浙江省  宁波市  *19761  *6201.0
河南省  郑州市  *05171  *5112.0
江苏省  南通市  *86953  *3998.0
江苏省  南京市  *89873  *3921.0
广东省  中山市  *73193  *2864.0
福建省  厦门市  *28397  *1956.0
福建省  福州市  *18773  *1131.0
江苏省  徐州市  *13849  *0009.0
山东省  青岛市  *85912  *441.0
天津    天津市  *83930  *964.0
广东省  汕头市  *75460  *821.0
河北省  邢台市  *77557  *648.0
湖南省  长沙市  *59106  *954.0
重庆    重庆市  *59921  *888.0
河北省  保定市  *50348  *637.0
河北省  石家庄市        *52024  *438.0
江苏省  无锡市  *50836  *348.0
浙江省  绍兴市  *42036  *059.0
山东省  济南市  *49028  *046.0
安徽省  合肥市  *39657  *972.0
江苏省  扬州市  *31576  *593.0
广东省  揭阳市  *29265  *519.0
times taken 6 seconds 



对查询速度影响

bash-3.2$ ./bluewhale higo sql "\" select count(empty_l) as cnt,dist(custid) as cid from rpt_p4padhoc_product where thedate range '20130201,20130228'  limit 0,40 \""
Running:  select count(empty_l) as cnt,dist(custid) as cid from rpt_p4padhoc_product where thedate range '20130201,20130228'  limit 0,40 
totalRecords:1
cnt     cid
*1*****7       ****4374
times taken 26 seconds
bash-3.2$ ./bluewhale higo sql "\" select count(empty_l) as cnt from rpt_p4padhoc_product where thedate range '20130201,20130228'  limit 0,40 \""
Running:  select count(empty_l) as cnt from rpt_p4padhoc_product where thedate range '20130201,20130228'  limit 0,40 
totalRecords:1
cnt
411697758
times taken 3 seconds 
./bluewhale higo sql "\" select count(empty_l) as cnt,sum(e_alipay_direct_amt) from rpt_p4padhoc_product where thedate range '20130201,20130228'  limit 0,40 \""
Running:  select count(empty_l) as cnt,sum(e_alipay_direct_amt) from rpt_p4padhoc_product where thedate range '20130201,20130228'  limit 0,40 
totalRecords:1
cnt     sum(e_alipay_direct_amt)
**1*****8       ****4464
times taken 11 seconds

关于计算精度的精度 请参见excel做的测试,10万个bit,能达到99%的精度 精度

有必要贴下实现的伪代码,供参考

public class DistinctCountExample {

	public static void main(String[] args) {
		run(1000);
		run(10000);
		run(100000);
		run(1000000);
		run(10000000);

	}
	
	public static void run(int uniq)
	{
		for(int j=1;j<10;j++)
		{
			DistinctCount dc=new DistinctCount();
			dc.setMaxUniqSize(10000);
			for(int i=0;i<uniq*j;i++)
			{
				dc.set("test_bit_"+i);
			}

			long uv=dc.getValue();
			int rate=(int) (Math.abs(uv-(uniq*j))*1000/(uniq*j));
			System.out.println("近似值:"+uv+",真实值:"+(uniq*j)+",误差:千分之"+rate);
		}
	}
	
	

}

Clone this wiki locally