5. 数据查询
欲看此文,必看如下两篇文章:
Druid支持JSON-over-HTTP和SQL两种查询方式。除了标准的SQL操作外,Druid还支持大量的唯一性操作,利用Druid提供的算法套件可以快速的进行计数,排名和分位数计算。

5.1 准备工作
5.1.1 导入大量数据
准备大量数据提供查询,我们插入1万条随机打车数据
- http://localhost:8010/taxi/batchTask/100000
复制代码
5.2.2 查看数据摄取进程
我们发现数据摄取进程正在运行,可以等待数据摄取任务结束

5.3 原生查询
Druid 最开始的时候是不支持 SQL 查询的,原生查询是通过查询 Broker 提供的 http server 来实现的
5.3.1 查询语法
- curl -L -H'Content-Type:application/json' -XPOST --data-binary @<query_json_file> <queryable_host>:<port>/druid/v2/?pretty
复制代码 5.3.2 查询案例
5.3.2.1 编辑查询JSON
- # 创建查询目录
- mkdir query
- # 编辑查询的JSON
- vi query/filter1.json
复制代码json 内容如下
- {
- "queryType":"timeseries",
- "dataSource":"message",
- "granularity":"month",
- "aggregations":[
- {
- "type":"count",
- "name":"taxiNum"
- }
- ],
- "filter":{"type":"selector","dimension":"status","value":1},
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码 5.3.2.2 参数解释
- queryType:查询类型,timeseries代表时间序列查询
- dataSource:数据源,指定需要查询的数据源是什么
- granularity:分组粒度,指定需要进行分组的粒度是什么样的
- aggregations:聚合查询:里面我们聚合了count,对数据进行统计
- filter:数据过滤,需要查询那些数据
- intervals:查询时间的范围,注意时间范围是前闭后开的,后面的日期是查询不到的
5.3.2.3 执行查询命令
在命名行中执行下面的命令会将查询json发送到对应的broker中进行查询--data-binary指定的查询json的路径
- curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter1.json http://192.168.64.177:8082/druid/v2/?pretty
复制代码我们查询了每个月发起打车的人数有多少

5.4 查询类型
druid查询采用的是HTTP RESTFUL方式,REST接口负责接收客户端的查询请求,客户端只需要将查询条件封装成JSON格式,通过HTTP方式将JSON查询条件发送到broker节点,查询成功会返回JSON格式的结果数据。了解一下druid提供的查询类型
5.4.1 时间序列查询
timeseries时间序列查询对于指定时间段按照查询规则返回聚合后的结果集,查询规则中可以设置查询粒度,结果排序方式以及过滤条件,过滤条件可以使用嵌套过滤,并且支持后聚合。
5.4.1.1 查询属性
时间序列查询主要包括7个主要部分
属性描述是否必须queryType该字符串总是"timeseries"; 该字段告诉Apache Druid如何去解释这个查询是dataSource用来标识查询的的字符串或者对象,与关系型数据库中的表类似。查看数据源可以获得更多信息是descending是否对结果集进行降序排序,默认是false, 也就是升序排列否intervalsISO-8601格式的JSON对象,定义了要查询的时间范围是granularity定义了查询结果的粒度,参见 Granularity是filter参见 Filters否aggregations参见 聚合否postAggregations参见Post Aggregations否limit限制返回结果数量的整数值,默认是unlimited否context可以被用来修改查询行为,包括 Grand Total 和 Zero-filling。详情可以看 上下文参数部分中的所有参数类型否5.4.1.2 案例
- {
- "queryType":"topN",
- "dataSource":"taxi_message",
- "dimension":"local",
- "threshold":2,
- "metric":"age",
- "granularity":"month",
- "aggregations":[
- {
- "type":"longMin",
- "name":"age",
- "fieldName":"age"
- }
- ],
- "filter":{"type":"selector","dimension":"sex","value":"女"},
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码 5.4.2 TopN查询
topn查询是通过给定的规则和显示维度返回一个结果集,topn查询可以看做是给定排序规则,返回单一维度的group by查询,但是topn查询比group by性能更快。metric这个属性是topn专属的按照该指标排序。
5.4.2.1 查询属性
topn的查询属性如下
属性描述是否必须queryType该字符串总是"TopN",Druid根据该值来确定如何解析查询是dataSource定义将要查询的字符串或者对象,与关系型数据库中的表类似。 详情可以查看 数据源 部分。是intervalsISO-8601格式的时间间隔,定义了查询的时间范围是granularity定义查询粒度, 参见 Granularities是filter参见 Filters否aggregations参见Aggregations对于数值类型的metricSpec, aggregations或者postAggregations必须指定,否则非必须postAggregations参见postAggregations对于数值类型的metricSpec, aggregations或者postAggregations必须指定,否则非必须dimension一个string或者json对象,用来定义topN查询的维度列,详情参见DimensionSpec是threshold在topN中定义N的一个整型数字,例如:在top列表中返回多少个结果是metric一个string或者json对象,用来指定top列表的排序。更多信息可以参见TopNMetricSpec是context参见Context否5.4.2.2 案例
查询每个季度年龄最小的女性的前两个的城市
- {
- "queryType":"topN",
- "dataSource":"message",
- "dimension":"local",
- "threshold":2,
- "metric":"age",
- "granularity":"quarter",
- "aggregations":[
- {
- "type":"longMin",
- "name":"age",
- "fieldName":"age"
- }
- ],
- "filter":{"type":"selector","dimension":"sex","value":"女"},
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码 5.4.2.3 执行查询
- curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/topN.json http://192.168.64.177:8082/druid/v2/?pretty
复制代码
5.4.5 分组查询
在实际应用中经常需要进行分组查询,等同于sql语句中的Group by查询,如果对单个维度和指标进行分组聚合计算,推荐使用topN查询,能够获得更高的查询性能,分组查询适合多维度,多指标聚合查询
5.4.5.1 查询属性
下表内容为一个GroupBy查询的主要部分:
属性描述是否必须queryType该字符串应该总是"groupBy", Druid根据该值来确定如何解析查询是dataSource定义将要查询的字符串或者对象,与关系型数据库中的表类似。 详情可以查看 数据源 部分。是dimension一个用来GroupBy的json List,详情参见DimensionSpec来了解提取维度的方式是limitSpec参见limitSpec否having参见Having否granularity定义查询粒度,参见 Granularities是filter参见Filters否aggregations参见Aggregations否postAggregations参见Post Aggregations否intervalsISO-8601格式的时间间隔,定义了查询的时间范围是subtotalsSpec一个JSON数组,返回顶级维度子集分组的附加结果集。稍后将更详细地描述它。否context参见Context否5.4.5.2 案例
每一季度统计年龄在21-31的男女打车的数量
- {
- "queryType":"groupBy",
- "dataSource":"taxi_message",
- "granularity":"Quarter",
- "dimensions":["sex"],
- "aggregations":[
- {
- "type":"count",
- "name":"taxiNum"
- }
- ],
- "filter":{
- "type":"bound",
- "dimension":"age",
- "lower":"21",
- "upper":"31",
- "alphaNumeric":true
- },
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码 5.4.5.3 执行查询
- curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/groupBy.json http://192.168.64.177:8082/druid/v2/?pretty
复制代码
5.5 查询组件
在介绍具体的查询之前,我们先来了解一下各种查询都会用到的基本组件,如Filter,Aggregator,Post-Aggregator,Query,Interval等,每种组件都包含很多的细节
5.5.1 Filter
Filter就是过滤器,在查询语句中就是一个JSON对象,用来对维度进行筛选和过滤,表示维度满足Filter的行是我们需要的数据,类似sql中的where字句。Filter包含的类型如下:
5.5.1.1 选择过滤器
Selector Filter的功能类似于SQL中的where key=value,它的json示例如下
- "Filter":{"type":"selector","dimension":dimension_name,"value":target_value}
复制代码使用案例
- {
- "queryType":"timeseries",
- "dataSource":"taxi_message",
- "granularity":"month",
- "aggregations":[
- {
- "type":"count",
- "name":"taxiNum"
- }
- ],
- "filter":{"type":"selector","dimension":"status","value":1},
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码 5.5.1.2 正则过滤器
Regex Filter 允许用户使用正则表达式进行维度的过滤筛选,任何java支持的标准正则表达式druid都支持,它的JSON格式如下:
- "filter":{"type":"regex","dimension":dimension_name,"pattern":regex}
复制代码使用案例,我们搜索姓名包含数字的的用户进行聚合统计
- {
- "queryType":"timeseries",
- "dataSource":"taxi_message",
- "granularity":"month",
- "aggregations":[
- {
- "type":"count",
- "name":"taxiNum"
- }
- ],
- "filter":{"type":"regex","dimension":"username","pattern":"[0-9]{1,}"},
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码执行查询
- curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter2.json http://192.168.64.177:8082/druid/v2/?pretty
复制代码
5.5.1.3 逻辑过滤器
Logincal Expression Filter包含and,not,or三种过滤器,每一种都支持嵌套,可以构建丰富的逻辑表达式,与sql中的and,not,or类似,JSON表达式如下:
- "filter":{"type":"and","fields":[filter1,filter2]}
- "filter":{"type":"or","fields":[filter1,filter2]}
- "filter":{"type":"not","fields":[filter]}
复制代码使用案例,我们查询每一个月,进行打车并且是女性的数量
- {
- "queryType":"timeseries",
- "dataSource":"taxi_message",
- "granularity":"month",
- "aggregations":[
- {
- "type":"count",
- "name":"taxiNum"
- }
- ],
- "filter":{
- "type":"and",
- "fields":[
- {"type":"selector","dimension":"status","value":1},
- {"type":"selector","dimension":"sex","value":"女"}
- ]
- },
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码进行数据查询
- curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter3.json http://192.168.64.177:8082/druid/v2/?pretty
复制代码
5.5.1.4 包含过滤器
In Filter类似于SQL中的in, 比如 where username in('zhangsan','lisi','zhaoliu'),它的JSON格式如下:
- {
- "type":"in",
- "dimension":"local",
- "values":['四川省','江西省','福建省']
- }
复制代码使用案例,我们查询每一个月,在四川省、江西省、福建省打车的人数
- {
- "queryType":"timeseries",
- "dataSource":"taxi_message",
- "granularity":"month",
- "aggregations":[
- {
- "type":"count",
- "name":"taxiNum"
- }
- ],
- "filter":{
- "type":"in",
- "dimension":"local",
- "values":["四川省","江西省","福建省"]
- },
- "intervals":["2021-06-07/2022-06-07"]
- }
复制代码进行数据查询
- curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter4.json http://192.168.64.177:8082/druid/v2/?pretty
复制代码
5.5.1.5 区间过滤器
<blockquote>
Bound Filter是比较过滤器,包含大于,等于,小于三种,它默认支持的就是字符串比较,是基于字典顺序,如果使用数字进行比较,需要在查询中设定alpaNumeric的值为true,需要注意的是Bound Filter默认的大小比较为>=或者 |