当前位置:首页>维修大全>综合>

phoenix的优缺点

phoenix的优缺点

更新时间:2023-06-23 18:05:21

phoenix的优缺点

1. 完全丧失了HBase的多版本特征

HBases至少也是三维结构(row、cf:cq、timestamp)的数据模型,Phoenix将其映射为二维的关系模型后,便面对着损失信息精度的尴尬场面。这种尴尬具体表现在Phoenix使用的两个方面:

a. 不能为一个cell指定任意的timestamp

作为HBase的第三维特征,timestamp的重要性不言而喻。由于绝大部分数据应用场景都离不开时间维度,所以我们经常会将数据中的某个时间字段映射到timestamp,也就无需在CF中存储该字段了。这样的好处是:既节约了存储空间,也可以使用timestamp相关的API(例如Get#setTimeRange)进行查询。

遗憾的是,Phoenix并不能让我们像HBase一样指定任意的timestamp。虽然Phoenix在 F.A.Q. 中煞有其事的提出了貌似这个问题的解决方案。但是深究之后你会发现这是一个比较坑爹的方案。理由如下:

首先,该方案貌似可以指定任意的timestamp,但是需要在应用程序中频繁的创建和关闭Connection,虽然他们还专门强调这不是一个“昂贵”的操作(is not an expensive operation),但是这样的代码风格估计会让很多人无语。

其次,该方案的任意timestamp其实是有条件的,即必须大于表的创建时间,否则,会出现“Table undefined”的异常。

需要说明的是,Phoenix可以Upsert重复的记录,每条记录的timestamp是不一样的。这样来看,虽然timestamp不是我期待的,但是多版本是不是已经实现了呢?看到下面的一点你应经就明白了。。。。。。

b. 不能获取一个cell的多个版本

Phoenix总是获取cell的最新版本,有没有办法去获取其它版本呢?

我曾经受 F.A.Q.中CurrentSCN属性的启发,自以为想到一个方法:不管三七二十一,先去拿一次,拿到的肯定是最新版本了。取其timestamp赋给PhoenixRuntime.CURRENT_SCN_ATTRIB后再去拿,这样就拿到次新版本了。以此类推,每次拿一个版本,直到拿不到而已。虽然这种方法有点笨,但是我想着总是可以解决问题的。但是后来突然发现一个致命的缺陷:如何取结果中的timestamp呢?呵呵,看来这个方法不单单是“有点笨”了......

相信这个问题也困扰了许多人,并引发了许多人的思考。 PHOENIX-590便是专门针对这个问题,遗憾的是,虽然提出了一些解决思路,但是至今仍然没有实质性的进展。

变通方案

PHOENIX-590提出了一种解决方案,其实也和我们想的一样。。。。。。就是将timestamp作为Phoenix表的单独一列,并且和其它字段作为组合主键。这样的本质是row和timestamp二维合成一维,反映在HBase里面,其实是将timestamp的值附加在row后面了。这样可以解决使用timestamp查询的问题,缺点是浪费了一些存储空间。

2. 二级索引设计比较粗糙

[sql] view plain copy print ?  

CREATE INDEX idx_name ON TAB_NAME(IDX_FIELD);

SELECT OtherField FROM TAB_NAME WHERR IDX_FIELD='';

我以为这样就可以利用索引了,但是其实不然,必须要

[sql] view plain copy print ?  

CREATE INDEX idx_name ON TAB_NAME(IDX_FIELD) INCLUDE(OtherField);

因为二级索引创建了一个新的索引表,没有INICLUDE时,索引表中的value为空,上述查询将不会利用索引表,而是Full Scan主表。INCLUDE时,会将OtherField字段写入索引表的value中,上述查询将会利用索引表进行Range Sacn。

这种做法让人不得不吐糟,虽然说存储不值钱,但是也不能这么浪费吧。

不过细想一下,这也是Phoenix的无奈之举:因为它不能保证主表和索引表对应Region的本地化,所以也就无法根据索引表的结果再去查主表了。

变通方案

a. 客户端自己解决:先查索引表获取Primary Key,然后根据Primary Key二次查询主表;

b. 使用其他索引方案......

针对目前Phoenix的二级索引方案,我个人建议一定要谨慎使用。鉴于其无与伦比的膨胀性,我建议只考虑使用在比较小的表上,并且对该表是写少读多。

更多栏目