Kudu系列: Kudu主键选择策略
每个Kudu 表必须设置Pimary Key(unique), 另外Kudu表不能设置secondary index, 经过实际性能测试, 本文给出了选择Kudu主键的几个策略, 测试结果纠正了我之前的习惯认知.
简单介绍测试场景: 表中有一个unqiue字段Id, 另外还有一个日期维度字段histdate, 有三种设置kudu PK的方法, 分别是:
表设计方案1 (histdate, id)作为联合主键, 日期字段放在前.
表设计方案2 (id,histdate)作为联合主键, 日期字段放在后.
表设计方案3 (id)作为单字段主键.
先给出测试数据:
结论:
1. 选择性强的字段(比如 id 字段) 应该放在PK清单最前面, 这个规则对查询性能影响最大.
2. PK清单中只加必要的字段, 越少越好.
3. 如果查询针对PK中所有字段都加了条件, 其性能是最优的. 但只要有一个PK字段未加上条件, 就完全用不上PK索引,性能就很差.
4. where条件中各个字段条件的先后顺序并不关键.
5. Kudu表使用Java API Insert的速度还是很好的, 单线程达到了1万笔/秒多. Kudu Update 效率也很高, 实测对一个窄表做全字段update, 其速度达到了Insert速度的88%, 而vertica的update效率比insert差很多.
在测试之前的误区:
误区1. (histdate,id)组合PK应该是最优的, 因为在数仓中经常按照日期做查询, 把日期放在PK清单最前面, 应该有助于提升查询性能, 结果发现无论是日期+id组合查询,还是id单独查询, 该方案性能都最差, 甚至不如完全不在PK清单中的 duplicated_id 的定位查询.
误区2. 即使给部分PK字段加上过滤条件, 查询也会利用上PK index, 结果证明是完全利用不上index.
具体表结构:
-- 下面三个表的 id 取值为: java.util.UUID.randomUUID().toString(), duplicated_id和id取值相同. CREATE TABLE kudu_testdb.perf_test_t1 ( histdate timestamp ENCODING BIT_SHUFFLE COMPRESSION LZ4, id string ENCODING PLAIN_ENCODING COMPRESSION SNAPPY, value int, duplicated_id string ENCODING PLAIN_ENCODING COMPRESSION SNAPPY, PRIMARY KEY (histdate,id) ) PARTITION BY HASH (histdate,id) PARTITIONS 2 STORED AS KUDU TBLPROPERTIES ( 'kudu.table_name' = 'testdb.perf_test_t1', 'kudu.master_addresses' = '10.205.6.1:7051,10.205.6.2:7051,10.205.7.3:7051' ); CREATE TABLE kudu_testdb.perf_test_t2 ( histdate timestamp ENCODING BIT_SHUFFLE COMPRESSION LZ4, id string ENCODING PLAIN_ENCODING COMPRESSION SNAPPY, value int, duplicated_id string ENCODING PLAIN_ENCODING COMPRESSION SNAPPY, PRIMARY KEY (id,histdate) ) PARTITION BY HASH (id,histdate) PARTITIONS 2 STORED AS KUDU TBLPROPERTIES ( 'kudu.table_name' = 'testdb.perf_test_t2', 'kudu.master_addresses' = '10.205.6.1:7051,10.205.6.2:7051,10.205.7.3:7051' ); CREATE TABLE kudu_testdb.perf_test_t3 ( id string ENCODING PLAIN_ENCODING COMPRESSION SNAPPY, histdate timestamp ENCODING BIT_SHUFFLE COMPRESSION LZ4, value int, duplicated_id string ENCODING PLAIN_ENCODING COMPRESSION SNAPPY, PRIMARY KEY (id) ) PARTITION BY HASH (id) PARTITIONS 2 STORED AS KUDU TBLPROPERTIES ( 'kudu.table_name' = 'testdb.perf_test_t3', 'kudu.master_addresses' = '10.205.6.1:7051,10.205.6.2:7051,10.205.7.3:7051' );