6.3. Ldrill多列联合倒排索引

6.3.1. 背景介绍

​ 近年来随着各个行业数据量的大幅度增长,使得存储费用和管理费用也随之增长,面对海量数据的OLAP需求,行存储数据库在统计数据的时候会消耗大量的时间做映射。对海量数据的操作,使得数据库性能受到计算机内存和硬盘的限制。为了减少存储费用和对机器配置的需求,数据库系统采用压缩数据的方法保存数据。为了方便OLAP的统计需求,采用了列存储数据的方法。但是传统的列存储是针对单列存储,多列之间并未建立关联,数据也没有按照顺序排列,这样在多列统计的场景效率提升并不明显。

现有技术存在的缺点:

  • 现有的列存储数据库当需要读取某条记录的所有属性的时候,列存储数据库不再高效。因为需要读取每个列属性文件的相应行的内容,浪费大量的IO时间。
  • 目前的列存储内部多列之间时独立排序,在基于多列的分组统计时消耗过多的cpu和io资源。
  • 现有的列存储数据库压缩比不高。

​ 现有的列存储数据库执行引擎访问数据的基本单位是单个属性值,列数据库对属性值的访问存在大量的跳跃访问和随机访问严重影响查询性能。

​ 常规的lucene是对单列建立倒排索引,包括字典和倒排表,数据存储的格式为行存,但是这种存储格式并不适合统计场景,当需要对单列进行分组的查询时,可以通过lucene的倒排表,因为原生lucene倒排表中term有序分组速度还可以接受,但是当对多列进行分组统计时就需要依赖lucene的docvalue,但是docvalue不是有序存储,所以只能将数据加载到内存做排序,效率不高。修改为对多列建立索引,有以下几个目的:

  • 加快统计与检索场景的速度。

  • 实现多层次关系分析。

  • 提升TopN排序速度。

  • 加快数据导出的速度。

6.3.2. 多列联合倒排索引 ldrill

1. 多列联合倒排索引特点

  • 每列之间采用列存储。
  • 预先干预数据的排序分布,让列存储的压缩更有效。
  • 依据查询构造顺序读取。
  • 多个列之间有层次关系。
  • 结合分块存储。

2. 应用场景

  • 统计与检索。
  • 多层次的关系分析。
  • TOP N排序。
  • 因存储连续,适合数据导出。

3.基本原理图

img

6.3.3. 使用方法

1. 基本概念

(1) olap_key:

  • 按照olap_key预先干预数据的分布

  • olap_key的每一列均是列存储

  • olap_key的每一列采用多种不同的压缩算法

  • 尽量将识别率高的列排在前面

 如用来过滤筛选的手机号,虽然压缩比一般,可以有效利用索引先过滤;

 或者那些重复值很高的列,如性别,省份,协议等 可以有非常高的压缩比。

(2) olap_value:

  • 跟随着olap_key后面存储,连续存储
  • 可以存储多个值,但并非按列存储,压缩方法采用lz4
  • 一般用来存储一些长文本数据
  • 不可以进行scan过滤

2. 建表方法

 create table olap_test(
   s_high y_string_is,
   s_middle y_string_is,
   s_low y_string_is,

   l_high y_long_is,
   l_middle y_long_is,
   l_low y_int_is,

   d_high y_double_is,
   d_middle y_double_is,
   d_low y_double_is,

   hlll_1 y_ldrill_imp 'olap_key@s_high,s_low,l_low,d_low' 'olap_value@l_high,d_high',
   hmll_2 y_ldrill_imp 'olap_key@l_high,l_middle,l_low,s_low' ,
   mlll_1 y_ldrill_imp 'olap_key@s_middle,s_low,l_low,d_low' 'olap_value@l_high,d_high',
   mmll_2 y_ldrill_imp 'olap_key@d_middle,l_middle,l_low,s_low' ,

   lllh_1 y_ldrill_imp 'olap_key@s_low,l_low,d_low,s_high' 'olap_value@s_low,d_high',
   llmh_2 y_ldrill_imp 'olap_key@l_low,s_low,l_middle,l_high'  ,
   lllm_1 y_ldrill_imp 'olap_key@s_low,l_low,d_low,s_middle' 'olap_value@s_low,d_high',
   llmm_2 y_ldrill_imp 'olap_key@l_low,s_low,d_middle,l_middle'  ,

   hl_1 y_ldrill_imp 'olap_key@s_high,s_low' 'olap_value@l_high,d_high',
   hm_2 y_ldrill_imp 'olap_key@l_high,l_middle'  ,
   ml_1 y_ldrill_imp 'olap_key@s_middle,s_low' 'olap_value@l_high,d_high',
   mm_2 y_ldrill_imp 'olap_key@d_middle,l_middle'  ,

   ll_1 y_ldrill_imp 'olap_key@s_low,l_low' 'olap_value@d_low',
   ll_2 y_ldrill_imp 'olap_key@l_low,s_low' 
 );

img

也可以结合列簇,将不同的列分开,存储到不同的存储介质中:

create columnfamily olap_test (
  default at 'index@true' 'store@false' ,
  hlll_1 at 'fields@hlll_1' 'index@true' 'store@false' ,
  hmll_2 at 'fields@hmll_2' 'index@true' 'store@false' ,
  mlll_1 at 'fields@mlll_1' 'index@true' 'store@false' ,
  mmll_2 at 'fields@mmll_2' 'index@true' 'store@false' ,                
  lllh_1 at 'fields@lllh_1' 'index@true' 'store@false' ,                                 
  llmh_2 at 'fields@llmh_2' 'index@true' 'store@false' ,
  lllm_1 at 'fields@lllm_1' 'index@true' 'store@false' ,
  llmm_2 at 'fields@llmm_2' 'index@true' 'store@false' ,
  hl_1 at 'fields@llmm_2' 'index@true' 'store@false'   ,
  hm_2 at 'fields@llmm_2' 'index@true' 'store@false'   ,
  ml_1 at 'fields@llmm_2' 'index@true' 'store@false'   ,
  mm_2 at 'fields@llmm_2' 'index@true' 'store@false'   ,
  ll_1 at 'fields@llmm_2' 'index@true' 'store@false'   ,
  ll_2 at 'fields@llmm_2' 'index@true' 'store@false' 
);

img

3. 查询使用方法

(1) 测试数据如下:

img

(2) 导入语句如下:

sh load.sh -t olap_test -p all_50yi_002 -tp txt -local -f /wyh/ldrill.log -sp , -fl s_high,s_middle,s_low,l_high,l_middle,l_low,d_high,d_middle,d_low

(3) 查看表数据:

img

(4) 仅扫描olap_key(按列存储,不需要的列不扫描)

select s_high,s_low,l_low from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'   limit 20;

img

(5) 同时扫描olap_key与olap_value

​ 注:olap_value不同的是整体压缩,查一个列与查询所有的列,IO是一样的,且olap_value里面的列不能参与过

滤, 也会加载doclist文件,速度略慢,但因为是顺序读,且有lz4压缩,性能一般也比docvalues快

select s_high,s_low,l_high from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'   limit 20;

img

(6) 带检索条件 from to,如果from==to相当于等值查询,尽量将需要过滤的列放在第一位,适合http协议那种根据key直接导出一批大的结果

  • 等值查询
select  s_high,s_low,l_low from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'  
and syskv='ldrill.form:SYS_URL_ENCODE@['za']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['za']@SYS_URL_ENCODE'  
limit 20;

img

  • 范围查询
select  s_high,s_low,l_low from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'  
and syskv='ldrill.form:SYS_URL_ENCODE@['za']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['zd']@SYS_URL_ENCODE'  
limit 20;

img

(7) 通配符*的使用

select  s_high,s_low,l_low from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'  
and syskv='ldrill.form:SYS_URL_ENCODE@['*','zc']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['*','zc']@SYS_URL_ENCODE'  
limit 20;

img

select  s_high,s_low,l_low from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'  
and syskv='ldrill.form:SYS_URL_ENCODE@['*','*','9']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_UR L_ENCODE@['*','*','16']@SYS_URL_ENCODE'  
limit 20;

img

(8) 也可以与其他检索条件组合使用,但是要借助doclist进行bitset比对,会有doclist的额外开销,性能相对于纯粹的from to会差一些。

select  s_high,s_low,l_low from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:hlll_1'  
and syskv='ldrill.form:SYS_URL_ENCODE@['*','*','9']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['*','*','16']@SYS_URL_ENCODE'  
and s_low='zc'  
limit 20;

img

(9) 统计

select l_low,count(*) from olap_test where partition like 'all_50yi_002'  and syskv='ldrill.name:ll_1'  group by l_low  limit 20;

img

(10) ldrill的统计是可以多列的,这是它的特点

select s_low,l_low,count(*) from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:ll_1'  group by s_low,l_low  limit 20;

img

(11) 对于某一个筛选值下面的统计,如筛选某一手机号,统计某一局部数据,这样筛选范围数据量就少了,而且这些数据还是连续存储

select d_middle,l_middle,count(*) from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:mm_2' 
and syskv='ldrill.form:SYS_URL_ENCODE@['30.0']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['50.0']@SYS_URL_ENCODE' 
group by d_middle,l_middle  
limit 20;

img

select l_middle,count(*),avg(d_middle),max(d_middle),min(d_middle),sum(d_middle) 
from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:mm_2' 
and syskv='ldrill.form:SYS_URL_ENCODE@['*','15256372889']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['*','15289790327']@SYS_URL_ENCODE' 
group by l_middle  
limit 20;

img

select d_middle,count(*),avg(l_middle),max(l_middle),min(l_middle),sum(l_middle) 
from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:mm_2' 
and syskv='ldrill.form:SYS_URL_ENCODE@['30.0']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['50.0']@SYS_URL_ENCODE' 
group by d_middle  limit 20;

img

(12) 数据导出,仅导出olap_key

export json overwrite /data/export/test2 select s_middle,s_low,l_low,d_low 
from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:mlll_1' 
and syskv='ldrill.form:SYS_URL_ENCODE@['zb']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['ze']@SYS_URL_ENCODE';

img

img

​ 注:该处测试所用的LSQL为单机版,故导出后文件存放在本地指定路径(如为集群版,则存放在HDFS上),

导出的文件数量与executor数有关。

(13) 数据导出,很多时候,往往需要将olap_value中的大块的值也导出去,这个时候只能读doclist,但是好在是顺序读取

export json overwrite /wyh/export/test2 select s_middle,s_low,l_low,d_low,l_high,d_high 
from olap_test where partition like 'all_50yi_002'  
and syskv='ldrill.name:mlll_1' 
and syskv='ldrill.form:SYS_URL_ENCODE@['zb']@SYS_URL_ENCODE'  
and syskv='ldrill.to:SYS_URL_ENCODE@['ze']@SYS_URL_ENCODE';

img

img

(14) group by只能做一种请求,如果一次请求要返回多种汇总数据,可以借助facet.

  • 不返回数据明细
select * from olap_test where partition like 'all_50yi_002' 
  and syskv='cl.facet.ldrill:SYS_URL_ENCODE@{'name':'ll_1','fl':'s_low,l_low','from':['*'],'to':['*']}@SYS_URL_ENCODE' 
  and syskv='cl.facet.ldrill:SYS_URL_ENCODE@{'name':'ll_2','fl':'l_low,s_low','from':['*'],'to':['*']}@SYS_URL_ENCODE'  
 limit 0;

img

  • 结合过滤筛选的facet
select * from olap_test where partition like 'all_50yi_002' 
  and syskv='cl.facet.ldrill:SYS_URL_ENCODE@{'name':'ll_1','fl':'s_low,l_low','from':['zc','5'],'to':['zi','12']}@SYS_URL_ENCODE' 
  and syskv='cl.facet.ldrill:SYS_URL_ENCODE@{'name':'ll_1','fl':'s_low,l_low','from':['zc','12'],'to':['zf','18']}@SYS_URL_ENCODE' 
  and syskv='cl.facet.ldrill:SYS_URL_ENCODE@{'name':'ll_2','fl':'l_low','from':['9'],'to':['17']}@SYS_URL_ENCODE'  
 limit 0;

img

4. 伴随分析

​ 伴随分析是一种常见的分析任务,常用来做同行、同住、同乘、同飞等碰撞分析。此处举例利用ldrill与RamIndexFilter相结合通过基站数据及手机MAC地址来快速对手机进行伴随分析。

img

(1) 建表

  • point_id y_string_is --手机的mac地址

  • mubiao_id y_string_is --基站ID

  • time_sec y_long_is --与基站交互的时间

  • time_min y_long_is --与基站交互的时间

create table tongxing (
point_id y_string_is
,mubiao_id y_string_is
,time_sec y_long_is
,time_min y_long_is
)
tableproperties(
ldrill=' olap_name@bansui olap_key@mubiao_id,time_min olap_value@point_id '
)

img

(2) 导入数据

sh load.sh -t tongxing -tp txt -local -f /wyh/testbasestation.txt -fl point_id,mubiao_id,time_sec,time_min -sp ,

img

(3) 全表扫描

img

(4) 通过基站对手机进行伴随分析

​ 通过待分析的手机MAC地址检索出该手机在某段时间内经过的所有基站,并将基站数据以及经过的该基站的时间(误差为±300s)放入RamIndexFilter中,再结合ldrill与全部数据集进行碰撞,快速返回伴随该手机的其他手机信息。

RamIndexFilter@0000000001:10240:over_rand@ 
select mubiao_id as id,from_unixtime(unix_timestamp(cast(time_min as string),'yyyyMMddHHmm')-300,'yyyyMMddHHmm') as time_start,from_unixtime(unix_timestamp(cast(time_min as string),'yyyyMMddHHmm')+300,'yyyyMMddHHmm') as time_end  from 
(
select mubiao_id,time_min from tongxing where partition like '%' and point_id='ebfe3ac2-50a3-4b74-856b-58e6d3a62ba6' 
) tmp
@RamIndexFilter
select point_id,count(*) as dist,sum(cnt) as cnt from (
select  point_id,mubiao_id,count(*) as cnt from tongxing  where partition like '%'  and syskv='ldrill.name:bansui'  and syskv='ldrill.form:RamIndexQuery@0,1@0,2@{RamIndexId:0000000001}'  group by point_id,mubiao_id 
) dist1  group by point_id order by dist desc
 limit 200;

返回结果集如下:

img

Copyright © lucene.xin 2020 all right reserved修改时间: 2021-07-02 11:42:23

results matching ""

    No results matching ""