Phoenix存储与查询性能研究

1、前期准备

数据表:轨迹信息表:TRACE_INFO

在这里插入图片描述

2、插入数据研究

目前不支持批量插入数据的接口,模拟只能循环插入数据,测试一个批量插入100000条数据,平均时间大概在190s。

在这里插入图片描述

在这里插入图片描述

目前表里已经有1000000条数据:
在这里插入图片描述

3、根据条数限制查询

查询100条(0.314s):
在这里插入图片描述

4、根据某个ID进行查询(0.175s)

ID 是唯一的主键
在这里插入图片描述

5、根据订单号进行查询(非主键,也无索引)(7.106s)

SELECT orderNo from TRACE_INFO where orderNo=‘59f47f95-a68a-4ab5-9589-a42cad5c4659’;

在这里插入图片描述

6、给订单号加个索引再查询

为订单号增加二级索引:

CREATE INDEX DATA_INDEX_ORDER_NO ON TRACE_INFO(ORDERNO);

在这里插入图片描述

索引表:

select * from DATA_INDEX_ORDER_NO;

在这里插入图片描述

继续查询:

SELECT orderNo from TRACE_INFO where orderNo=‘59f47f95-a68a-4ab5-9589-a42cad5c4659’;

在这里插入图片描述

查询计划分析:

EXPLAIN SELECT orderNo from TRACE_INFO where orderNo=‘59f47f95-a68a-4ab5-9589-a42cad5c4659’;

走的是我们刚刚建立的订单号索引:

在这里插入图片描述

如果我们把查询内容改成时间,再看看:

SELECT startTime from TRACE_INFO where orderNo=‘59f47f95-a68a-4ab5-9589-a42cad5c4659’;

在这里插入图片描述

发现需要7.917s,依旧很慢,为什么我们给订单号加了二级索引,而查询也是根据订单号查询,区别在于查询的不是订单号,而是时间。(第一种情形)

查询计划分析显示:全表扫描

在这里插入图片描述

我们再看另一种情况,我们在前面查询订单号的基础上,增加时间的查询条件再看下:7.743s(第二种情形)

在这里插入图片描述

依然是全表扫描

在这里插入图片描述

分析两种情况的原因:

第一种:

官网索引:Global mutable index will not be used unless all of the columns referenced in the query are contained in the index.

orderNo字段虽然是索引字段但是startTime字段并不是索引字段,也就是说需要查询出来的字段必须都是索引字段

第二种:查询条件startTime不是索引

那么此时把startTime也加入二级索引:

CREATE INDEX DATA_INDEX_START_TIME ON TRACE_INFO(startTime);

在这里插入图片描述

再进行前面2种查询:

在这里插入图片描述

在这里插入图片描述

发现没有用到索引,那么我们把建立的索引都删除,建立覆盖索引试试:

drop index DATA_INDEX_ORDER_NO on TRACE_INFO;

drop index DATA_INDEX_START_TIME on TRACE_INFO;

在这里插入图片描述

创建覆盖索引:

CREATE INDEX IDX_COVER on TRACE_INFO(orderNo) include (startTime);

再来查询,性能陡然上升:

在这里插入图片描述

原因:索引覆盖其实就是将INCLUDE里面包含的列都存储到索引表里面,当检索的时候就可以从索引表里直接带回这些列值。要特别注意索引列和索引覆盖列的区别,索引列在索引表里面是以rowkey的形式存在,

多个索引列以某个约定的字节分割然后一起存储在rowkey里面,也就是说当索引列有很多个的时候,rowkey的长度也相应会变长,大小取决于索引列值的大小。而索引覆盖列,是存储在索引表的列族中。但是

使用这种方式创建的所有会导致startTime字段的值被拷贝到索引中,缺点就是会导致索引表大小有一定的增加。

查询索引表my_index结构,增加了startTime这列:

在这里插入图片描述

除了建立覆盖索引的优化手段,还可以采用组合索引方式:可以创建组合索引来解决多个条件查询索引命中问题,组合索引的第一个字段必须要在查询条件中

先去掉覆盖索引:

drop index IDX_COVER on TRACE_INFO;

再建立组合索引:

create index IDX_GROUP on TRACE_INFO(orderNo,startTime);

继续查询:

在这里插入图片描述

同样有效果!

注意:多列索引在满足前缀式的情况才会用到,如创建了A,B,C顺序的多列索引,当在where条件指定A条件、A B条件或者A B C条件均会走索引,但是 B C条件则无法走索引。(类似MYSQL的最左前缀匹配)

7、结论:

功能页面多一个查询条件,就要多建立好几个二级索引。才能满足速度要求。

比如orderNo 和 startTime,都不是必填项。

用户可能只输入orderNo ,需要1个二级索引;可能只输入startTime,需要1个二级索引;可能同时输入两个,需要1个二级索引。

简单的两个条件,就要3个索引。

比如页面有6个查询条件!!需要多少二级索引!!! 几何倍增长,通常同一张表,索引数量不得超过10,索引表越多,插入数据越慢。

1、从需求方面 (大数据查询,不适合太多条件的查询)。无意义的查询条件,统统去掉。

 需要规定一个必填的查询字段,比如最通用的:时间(yyyy-MM-dd)..

2、从表设计方面,row key可以是联合主键。可以利用这点,减少二级索引数量。比如ID 就是主键。

3、从逻辑方面,比如我需要这几个查询条件,需要几个二级索引,可以采用覆盖索引,或者建立联合索引。

8、关于索引

全局索引适用于读频繁的场景。对于全局索引,所有性能消耗都发生在写入时,所有对业务表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),会引起索引的更新,

而索引是分布在不同的节点上的,跨节点的数据传输带来了较大的性能消耗。在读数据的时候 Phoenix 会选择最快的索引,把它当作一般的 HBase 表来扫描,而不去扫描业务表。

在默认情况下,没有指定强制使用索引,如果查询的字段没有在索引列的话,这种情况下索引不会被使用。

本地索引适用于写频繁、且存储空间有限的场景。和全局索引一样,Phoenix 会在查询时自动选择是否使用本地索引。使用本地索引,索引数据和表数据会写到同一个 Region Servers 上,

从而避免了写入期间的网络开销。本地索引即使未完全覆盖业务表的所有字段,在查询的时候也会使用索引(Phoenix 会自动检索索引之外的字段,通过点查询业务表获得数据)。

不同于全局索引,在4.8.0版本之前,业务表的所有本地索引都存储在一个单独的共享表中。在4.8.0版本之后,所有的本地索引数据都被存储在同一业务表的单独列族中。

在使用本地索引的读取数据时,因为不能预先确定索引数据的确切区域位置,因而会对读取速度有一定的影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值