备注: 本页描述的功能为在当前版本中技术预览(开发完成但未经充分测试)功能。
支持多温度数据
Trafodion设计蓝图描述cmp-divisioning
随着历史数据量的增加,保留着当前和历史数据的数据库经常会面临性能降低的问题。大多数数据库系统会提供特别功能来避免这个性能和扩展性问题,通常通过确保最近的(或"热")数据从较旧的 ("冷") 数据中分离出来单独存储。
最常见的方式做到这一点是范围分区:对于每个时间间隔 (例如每周、 月或年),创建一个单独的分区。这确保所有热数据能在最新的分区被找到,或在某些情况下,最近的两个分区。这种类型的范围分区会在Oracle, Hive, DB2和其他许多系统中出现。
在 Trafodion,我们想要通过略有不同的方式创建逻辑(非物理)范围分区的方式实现多温度数据。我们是通过增加范围分区号作为键值的前缀,这样热数据一起被存储在键值范围而那冷数据存储在不同的键值范围。这某种程度上类似于Teradata的Partitioned Primary Index (PPI)。我们期望这些逻辑范围分区会存在在每个region,这是通过salting来实现的。范围分区号是一个计算获得的系统列,意味着它通常不是用户可见的,它由 Trafodion自动维护。
为了说明这一点,下面是一个示例:
比方说,我们正在存储"call home"数据。我们有100000的设备,这些设备每10秒发送一次状态更新,从而导致每一秒有10000行插入到表中。表格DDL如下:
DDL版本1:
create table call_home_data(
id largeint not null,
ts timestamp(6) not null,
device_status varchar(200),
primary key (id, ts));
使用(id,ts)作为 HBase 行键,插入数据随机遍布于多个region(假设设备负载均衡)并且冷热数据是混合的的数据。为了隔离冷和热数据,我们可以先打上时间戳:
DDL版本2:
create table call_home_data(
id largeint not null,
ts timestamp(6) not null,
device_status varchar(200),
primary key (ts, id));
然而,这将造成在最后一个region过热点以及在一个给定的时间内查询单个设备将需要扫描其他设备的所有数据。通常的解决方法是通过实践来范围分区表格,比如一天建一个分区。拟议的Trafodion语法如下所示:
DDL版本3:
create table call_home_data(
id largeint not null,
ts timestamp(6) not null,
device_status varchar(200),
primary key (id, ts))
division by (date_trunc('day', ts);
这功能称为第“divisioning”而不是“分区(partitioning)”是由于历史原因。它将创建新列,“_DIVISION_0_”总是保存交易记录的时间戳的日期。Hbase行键为(“_DIVISION_0_”, id, ts)。然而这又再导致了在最后一个region的过热点,所有数据插入表格都会在在这个region。所以我们需要使用撒盐功能(salting):
DDL版本4:
create table call_home_data(
id largeint not null,
ts timestamp(6) not null,
device_status varchar(200),
primary key (id, ts))
salt using 16 partitions on (id)
division by (date_trunc('day', ts);
现在Hbase行键由四列构成:(“_SALT_”, “_DIVISION_0_”, id, ts)。
“_SALT_”是id的哈希值它将数据均匀地分布在 16 个region。"_DIVISION_0_"是交易时间戳的日期,它将一天的数据保存在一个紧凑的键值范围,这样能更有效insert和select操作。
一个典型的查询如下所示:
select *
from call_home_data
where id = 123456
and ts between timestamp '2014-11-11 11:11:11.111111'
and timestamp '2014-11-12 01:00:00.000000';
Trafodion将自动生成计算生成的“_SALT_”和“_DIVISION_0_”的预测。因为查询有相同的id预测,同样我们能生成等值的_SALT_预测:“_SALT_” = HASH2PARTFUNC(123456 for 16)。ts范围的预测转换成了“_DIVISION_0_”范围的预测:“_DIVISION_0_”时间戳介于'2014-11-11 00:00:00.000000'和'2014-11-12 00:00:00.000000'之间。我们能通过使用MDAM去访问那些查询指定的id和ts值。
比较四个DDL版本:
特性 | DDL 1 | DDL 2 | DDL 3 | DDL 4 |
---|---|---|---|---|
数据插入跨所有region | 是 | 否 | 否 | 是 |
数据访问平衡于各region | 或许 | 否 | 否 | 是 |
冷热数据隔离 | 否 | 是 | 是 | 是 |
基于id优化查询 | 是 | 否 | MDAM | MDAM |
基于时间范围优化查询 | 否 | 是 | 是 | MDAM |
基于id和时间的优化查询 | 是 | 否 | 是 | 是 |
DIVISION BY 语法
DIVISION BY (div_expr_list)
div_expr_list 是一个表达式列表,它只能引用主键或STORE BY的列。
DIVISION BY子句中合法的表达式列表如下(请注意所有这些都单调递增的表达式):
- cast((exact_numeric_column[ + const1 ] ) / const2 as numeric_data_type)
- DATE_PART('YEAR', date_part_arg )
- DATE_PART('YEARQUARTER', date_part_arg )
- DATE_PART('YEARMONTH', date_part_arg )
- DATE_PART('YEARWEEK', date_part_arg )
- DATE_TRUNC(const, datetime_col)
- DATEDIFF(YEAR, const, datetime_col)
- DATEDIFF(QUARTER, const, datetime_col)
- DATEDIFF(MONTH, const, datetime_col)
- DATEDIFF(WEEK, const, datetime_col)
- LEFT(character_col, const)
- SUBSTR[ING](character_col, 1, const)
- SUBSTR[ING](character_col FROM 1 FOR const)
date_part_arg 是下列之一:
- datetime_col
- datetime_col + const
- datetime_col - const
- ADD_MONTHS(datetime_col, const [, 0])
- DATE_ADD(datetime_col, const)
- DATE_SUB(datetime_col, const)