三、采样算法以下是个人的一些娱乐性思考
- 等比放大 , 即(采样得到distinct值 / 采样行数) x 总行数 。举个例子 , 假设表有1000行数据 , 只采样100行 , A列有95个不同的值 , 即count(distinct A) / count(A) = 95% , 那么等比放大很容易推导出1000行数据 , 有950个A的不同值 。但是如果这100行中B列只有2个不同的值 , 即count(distinct B) / count(B) = 2% , 那么对于1000行的表来讲 , B的不同值是不是等于2% * 1000呢?很有可能不是 , 说不定全表就这两个不同值 , 例如性别 。所以通过等比放大得到的distinct值就不准 。这种算法有明显的缺陷 。
- 按增长率估算 , 即将采样得到的前5%作为一个基数 , 采样得到的后5%作为一个增长率 。(假设采样比例是10%)还是举个例子 , 假设表有1000行数据 , 只采样100行 , 采样的前50行 , C列有40个不同值 。采样的后50行 , C列又多了30个不同值 , 即总共有70个不同值 。那么后面的90%都会保持这个增长速度 。则总体的C列不同值为40 + 30 * ((100-5)/5) = 610 。再来看一种情况 , 假设采样的前50行 , D列有2个不同值 。采样的后50行 , D列多了0个不同值 , 即不同值总数保持不变 。那么后面的90%都会保持这个增长速度 。则总体的D列不同值仍为2 。这种方式似乎比等比采样更加合乎实际情况一点 。接下来就用python去实现这个算法 , 看看与oracle的估算差别有多大 。以下为python代码 。
import randomimport cx_Oracledef func(ins):SAMPLE_PERCENT = 10# 采样比例%sample_size = int(len(ins) * SAMPLE_PERCENT / 100)# 对数据进行采样sample = random.sample(ins, sample_size)head_half_sample = sample[0:int(len(sample)/2)]# 采样数据的前一半head_half_sample_distinct = len(set(head_half_sample))# 采样数据的前一半的distinct值full_sample_distinct = len(set(sample))# 采样数据的全量distinct值tail_half_inc = full_sample_distinct - head_half_sample_distinct# 采样数据的distinct增量estimate_distinct = round(head_half_sample_distinct + tail_half_inc * (100 - SAMPLE_PERCENT/2) / (SAMPLE_PERCENT/2))return estimate_distinctdef test(colname):DATABASE_URL = 'xxxxx'conn = cx_Oracle.connect(DATABASE_URL)curs = conn.cursor()sql = 'select {} from t1'.format(colname)curs.execute(sql)tmpdata = https://www.huyubaike.com/biancheng/[]for i in curs.fetchall():tmpdata.append(i[0])res = func(tmpdata)curs.close()conn.close()return resfor i in ['OBJECT_NAME', 'SUBOBJECT_NAME', 'TIMESTAMP', 'LAST_DDL_TIME', 'CREATED', 'NAMESPACE', 'OBJECT_TYPE','OWNER', 'TEMPORARY', 'DUPLICATED', 'STATUS', 'SHARDED', 'GENERATED', 'SECONDARY', 'SHARING', 'EDITIONABLE','ORACLE_MAINTAINED', 'APPLICATION', 'DEFAULT_COLLATION', 'DATA_OBJECT_ID', 'OBJECT_ID']:print(i, '估算的distinct->', test(i))
运行结果文章插图
再来跟之前的一个表格进行对比 , 按增长率的方式估算的distinct值看上去也能接受 。
COLUMN_NAME实际的distinct数据库估算的distinctpython估算的distinct------------------------------ -------------------------------------------------------OBJECT_NAME645521030074865SUBOBJECT_NAME10153851210TIMESTAMP258512405641LAST_DDL_TIME249012575536CREATED231212094983NAMESPACE211589OBJECT_TYPE453992OWNER8071176TEMPORARY222DUPLICATED111STATUS222SHARDED111GENERATED222SECONDARY111SHARING444EDITIONABLE223ORACLE_MAINTAINED222APPLICATION111DEFAULT_COLLATION112DATA_OBJECT_ID777857810077752OBJECT_ID145212146100145178
限于时间 , 测试到此结束 。后面有时间再学点统计相关的知识 。
经验总结扩展阅读
- 纸嫁衣4红丝缠公交车统计表怎么解迷
- 1分钟完成在线测试部署便捷收集班级同学文件的web管理系统
- 2023二本统计学好找工作吗 就业方向有哪些
- 在CentOS7下安装Oracle11教程
- 图文超详解 G1 垃圾收集器深入剖析
- Oracle中查询表结构的六种方法
- 高考人数比去年增加多少人呢,高考历年人数统计表
- 高考人数大概会是多少,近几年高考人数统计汇总
- 4 探究Presto SQL引擎-统计计数
- 原神证悟木怎么快速收集