phoenix 联合主键的探索

环境:phoenix 5.0 hbase2.0

连接上phoenix,建一个测试表:

create table test12(email varchar not null,id integer not null,name varchar not null,age integer,aihao varchar CONSTRAINT PK PRIMARY KEY (EMAIL,id,name));

这是3个字段组成的联合主键。

刚接触时,由于查询的条件较多。我曾想着把所有字段都设置成主键。那不是全部搞定了,哈哈哈。(别做梦,醒一醒,年轻人)

显然将所有字段都设计成,主键是不合理的。

我认为phoenix 主键的目的有两点:

1、与关系型数据库一样,唯一标识数据。

或许会用到这种语句:

UPSERT INTO TEST(ID, MY_COL) VALUES(123, 0) ON DUPLICATE KEY IGNORE;

 

2、作为查询的条件。

Hbase 的 rowKey 就是快。

 

开了个小差,回到正题:

测试表联合主键的先后顺序是(EMAIL,id,name)

那么如下SQL,有区别吗?

select * from test12 where email='a' and id=1;

select * from test12 where id=1 and email='a';

看一下执行计划

explain select * from test12 where email='a' and id=1;

explain select * from test12 where id=1 and email='a';

两个结果相同:

虽然会自动优化成相同的顺序,建议写条件时,还是按照顺序来写SQL。

 

其实还有一种情况,我遇到了,特别记录:

test3与 test13表:

这两张表字段全部相同,只是主键的顺序不同,我用来做对比的。

 

与之关联的表是test4:

问:

test3 与 test4 inner join

test13 与 test4 inner join

test3、test13 的条件也都相同,结果会不同吗?

 

先看test3的SQL 与 执行计划:

SELECT T1.LOGIN_DATE,T1.COUNTRY,T1.IP,T1.BROWSER,T1.USER_NAME,T1.GENDER,T1.EMAIL,T2.TIME_SPEND,T2.CAM_SITE,T2.TOKEN_EARNED,T2.REVENUE,T2.TIPS_SENT,T2.TOY FROM TEST4 T1 INNER JOIN (SELECT SEQ_ID,SHOW_DATE,EMAIL,TIME_SPEND,CAM_SITE,TOKEN_EARNED,REVENUE,TIPS_SENT,TOY FROM TEST3 WHERE SEQ_ID>=45665 AND SHOW_DATE='2018-11-13' ORDER BY SEQ_ID LIMIT 20) T2 ON (T1.LOGIN_DATE = T2.SHOW_DATE AND T1.EMAIL = T2.EMAIL)
WHERE T1.COUNTRY='China' AND T1.USER_NAME='wjc';

 

再看test13 的SQL 与 执行计划

SELECT T1.LOGIN_DATE,T1.COUNTRY,T1.IP,T1.BROWSER,T1.USER_NAME,T1.GENDER,T1.EMAIL,T2.TIME_SPEND,T2.CAM_SITE,T2.TOKEN_EARNED,T2.REVENUE,T2.TIPS_SENT,T2.TOY FROM TEST4 T1 INNER JOIN (SELECT SEQ_ID,SHOW_DATE,EMAIL,TIME_SPEND,CAM_SITE,TOKEN_EARNED,REVENUE,TIPS_SENT,TOY FROM TEST13 WHERE SEQ_ID>=45665 AND SHOW_DATE='2018-11-13' ORDER BY SEQ_ID LIMIT 20) T2 ON (T1.LOGIN_DATE = T2.SHOW_DATE AND T1.EMAIL = T2.EMAIL)
WHERE T1.COUNTRY='China' AND T1.USER_NAME='wjc';

细心的你看出不同了吗?哈哈哈,明显test13 与 test4 inner join更加合适。

结论:第一个主键不适合,序列号等,唯一标识的列。

 

让我们继续:

再看一下,这两个有区别吗?

select * from test12 where id=1;

select * from test12 where email='a';

执行计划:

条件为id的是全表扫描,而email是范围扫描。效率可想而知。

 

这种情况也是会进行范围扫描,但name条件走的是过滤筛选。

select * from test12 where email='a' and name='b';

 

结论:

如果有相关的页面、或者业务逻辑。

那么设计联合主键时,第一个主键,建议是必填的、使用频率最高的、值存在重复的。

 

关于提高查询效率,还有二级索引可以使用。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值