如何通过Druid原生查询获取最新值及去除重复记录?
一、从Druid原生查询获取最新值
可以通过以下两种常用方式实现:
1. 使用TopN查询(推荐)
TopN查询适合快速获取基于时间排序的最新记录,性能优于Scan查询:
{ "queryType": "topN", "dataSource": "your_datasource_name", "intervals": ["2000-01-01/3000-01-01"], // 覆盖全时间范围 "granularity": "all", "dimension": "__time", // 按时间维度排序 "metric": { "type": "numeric", "metric": "__time", "ordering": "descending" // 降序取最新时间 }, "threshold": 1, // 只返回1条结果 "aggregations": [ // 聚合你需要的字段,这里以long类型字段为例 { "type": "longSum", "name": "latest_value", "fieldName": "your_target_field" } ] }
如果需要获取原始行数据,可将aggregations替换为postAggregations或结合子查询关联原始数据。
2. 结合GroupBy与Scan查询
先通过GroupBy获取最新时间戳,再用Scan查询匹配该时间的记录:
{ "queryType": "scan", "dataSource": { "type": "subquery", "query": { "queryType": "groupBy", "dataSource": "your_datasource_name", "intervals": ["2000-01-01/3000-01-01"], "granularity": "all", "dimensions": [], "aggregations": [ { "type": "max", "name": "latest_time", "fieldName": "__time" } ] } }, "intervals": ["2000-01-01/3000-01-01"], "limit": 1 }
二、Scan查询去重并仅返回一条结果
针对Scan查询返回重复记录的问题,可从查询层面或源头优化:
1. 查询层面去重
方式1:排序后限制返回条数
如果重复记录存在时间差异,可按时间降序排序后取第一条,自动忽略旧的重复记录:
{ "queryType": "scan", "dataSource": "your_datasource_name", "intervals": ["2000-01-01/3000-01-01"], "sortSpec": { "fields": [ { "dimension": "__time", "direction": "descending" }, // 若同时间存在重复,可增加唯一ID维度排序确保只取一条 { "dimension": "unique_record_id", "direction": "descending" } ] }, "limit": 1 }
方式2:子查询过滤重复值
如果重复记录基于某个唯一标识字段,先通过TopN获取该字段的唯一值,再用Scan查询匹配:
{ "queryType": "scan", "dataSource": { "type": "subquery", "query": { "queryType": "topN", "dataSource": "your_datasource_name", "intervals": ["2000-01-01/3000-01-01"], "granularity": "all", "dimension": "unique_record_id", "metric": { "type": "numeric", "metric": "__time", "ordering": "descending" }, "threshold": 1 } }, "intervals": ["2000-01-01/3000-01-01"], "limit": 1 }
2. 源头优化(推荐)
如果重复记录是摄入阶段产生的,建议在Druid摄入规范中配置uniqueKeySpec,从根源避免重复数据存储:
// 摄入规范示例 { "type": "kafka", "dataSource": "your_datasource_name", "uniqueKeySpec": { "type": "string", "column": "unique_record_id" // 用于判断重复的唯一字段 }, // 其他摄入配置... }
内容的提问来源于stack exchange,提问作者shamanth gowda
相关产品推荐
相关产品推荐

