统计数据也是带时间属性的,统计数据最小单位只会到分钟(到秒预统计就没意义了)。同时对于统计数据我们也缺省采用按天数据分表,这样设计的好处无需多说。按天分表后,时间信息只需要保留小时分钟,那么0~1400只需占用两个字节即可保存时间信息。由于统计数据某些维度数量非常庞大,因此需要4个字节作为序列字段,因此将散列字段同时作为序列字段使用也是6个字节组成唯一Rowkey。如下图所示:
统计数据Rowkey设计
第0字节
第1字节
第2字节
第3字节
第4字节
第5字节
…
散列字段(序列字段)
时间字段(分钟)
扩展字段
0x00000000~0xFFFFFFFF)
0~1439(0x0000~0x059F)
同样这样的设计从操作系统内存管理层面无法节省开销,因为64位操作系统是必须8字节对齐。但是对于持久化存储中Rowkey部分可以节省25%的开销。预统计数据可能涉及到多次反复的重计算要求,需确保作废的数据能有效删除,同时不能影响散列的均衡效果,因此要特殊处理。
针对通用数据的Rowkey设计
通用数据采用自增序列作为唯一主键,用户可以选择按天建分表也可以选择单表模式。这种模式需要确保同时多个入库加载模块运行时散列字段(序列字段)的唯一性。可以考虑给不同的加载模块赋予唯一因子区别。设计结构如下图所示。
通用数据Rowkey设计
第0字节
第1字节
第2字节
第3字节
…
散列字段(序列字段)
扩展字段(控制在12字节内)
0x00000000~0xFFFFFFFF)
可由多个用户字段组成
支持多条件查询的RowKey设计
下面举个形象的例子:
我们在表中存储的是文件信息,每个文件有5个属性:文件id(long,全局唯一)、创建时间(long)、文件名(String)、分类名(String)、所有者(User)。
我们可以输入的查询条件:文件创建时间区间(比如从20120901到20120914期间创建的文件),文件名(“快乐大本营”),分类(“综艺”),所有者(“浙江卫视”)。
假设当前我们一共有如下文件:
内容列表 ID CreateTime Name Category UserID 1 2 3 4 5 6 7 8 9 10
20120902
快乐大本营第1期
综艺
1
20120904
快乐大本营第2期
综艺
1
20120906
快乐大本营番外
综艺
1
20120908
快乐大本营第3期
综艺
1
20120910
快乐大本营第4期
综艺
1
20120912
快乐大本营嘉宾采访
综艺花絮
2
20120914
快乐大本营第5期
综艺
1
20120916
快乐大本营录制花絮
综艺花絮
2
20120918
王祖蓝独家专访
花絮
3
20120920
安慕希酸奶广告
综艺广告
4
这里UserID应该对应另一张User表,暂不列出。我们只需知道UserID的含义:
1代表 浙江卫视; 2代表 大本营剧组; 3代表 XX微博; 4代表 赞助商。
调用查询接口的时候将上述5个条件同时输入find(20120901,20121001,"快乐大本营","综艺","浙江卫视")。
此时我们应该得到记录应该有第1、2、3、4、5、7条。第6条由于不属于“浙江卫视”应该不被选中。
我们在设计RowKey时可以这样做:采用UserID + CreateTime + FileID组成rowKey,这样既能满足多条件查询,又能有很快的查询速度。