您当前的位置:首页 > 电脑百科 > 数据库 > 百科

面对千万级数据查询,CK、ES、RediSearch谁才是王炸?

时间:2022-09-08 16:05:48  来源:  作者:dbaplus社群

前言

在开发中遇到一个业务诉求,需要在千万量级的底池数据中筛选出不超过 10W 的数据,并根据配置的权重规则进行排序、打散(如同一个类目下的商品数据不能连续出现 3 次)。

下面对该业务诉求的实现,设计思路和方案优化进行介绍,对「千万量级数据中查询 10W 量级的数据」设计了如下方案:

  • 多线程 + CK 翻页方案
  • ES scroll scan 深翻页方案
  • ES + Hbase 组合方案
  • redisearch + RedisJSON 组合方案

一、初版设计方案

整体方案设计为:

  • 先根据配置的「筛选规则」,从底池表中筛选出「目标数据」。
  • 在根据配置的「排序规则」,对「目标数据」进行排序,得到「结果数据」。

技术方案如下:

  • 每天运行导数任务,把现有的千万量级的底池数据(Hive 表)导入到 Clickhouse 中,后续使用 CK 表进行数据筛选。
  • 将业务配置的筛选规则和排序规则,构建为一个「筛选 + 排序」对象 SelectionQueryCondition。
  • 从 CK 底池表取「目标数据」时,开启多线程,进行分页筛选,将获取到的「目标数据」存放到 result 列表中。
  •  

//分页大小 默认 5000

int pageSize = this.getPageSize();

//页码数

int pageCnt = totalNum / this.getPageSize() + 1;

List<Map<String, Object>> result = Lists.newArrayList();

List<Future<List<Map<String, Object>>>> futureList = new ArrayList<>(pageCnt);

//开启多线程调用

for (int i = 1; i <= pageCnt; i++) {

//将业务配置的筛选规则和排序规则 构建为 SelectionQueryCondition 对象

SelectionQueryCondition selectionQueryCondition = buildSelectionQueryCondition(selectionQueryRuleData);

selectionQueryCondition.setPageSize(pageSize);

selectionQueryCondition.setPage(i);

futureList.add(selectionQueryEventPool.submit(new QuerySelectionDataThread(selectionQueryCondition)));

}

for (Future<List<Map<String, Object>>> future : futureList) {

//RPC 调用

List<Map<String, Object>> queryRes = future.get(20, TimeUnit.SECONDS);

if (CollectionUtils.isNotEmpty(queryRes)) {

// 将目标数据存放在 result 中

result.addAll(queryRes);

}

}

  • 对目标数据 result 进行排序,得到最终的「结果数据」。

二、CK分页查询

在「初版设计方案」章节的第 3 步提到了「从 CK 底池表取目标数据时,开启多线程,进行分页筛选」。此处对 CK 分页查询进行介绍。

  • 封装了 queryPoolSkuList 方法,负责从 CK 表中获得目标数据。该方法内部调用了 sqlSession.selectList 方法。
  •  

public List<Map<String, Object>> queryPoolSkuList( Map<String, Object> params ) {

List<Map<String, Object>> resultMaps = new ArrayList<>();

QueryCondition queryCondition = parseQueryCondition(params);

List<Map<String, Object>> mapList = lianNuDao.queryPoolSkuList(getCkDt(),queryCondition);

if (CollectionUtils.isNotEmpty(mapList)) {

for (Map<String,Object> data : mapList) {

resultMaps.add(camelKey(data));

}

}

return resultMaps;

}

  •  

// lianNuDao.queryPoolSkuList

@Autowired

@Qualifier("ckSqlNewSession")

private SqlSession sqlSession;

public List<Map<String, Object>> queryPoolSkuList( String dt, QueryCondition queryCondition ) {

queryCondition.setDt(dt);

queryCondition.checkMultiQueryItems();

return sqlSession.selectList("LianNu.queryPoolSkuList",queryCondition);

}

  • sqlSession.selectList 方法中调用了和 CK 交互的 queryPoolSkuList 查询方法,部分代码如下。
  •  

<select id="queryPoolSkuList" parameterType="com.jd.bigAI.domain.liannu.QueryCondition" resultType="JAVA.util.Map">

select sku_pool_id,i

tem_sku_id,

skuPoolName,

price,

businessType

from liannu_sku_pool_indicator_all

where

dt=#{dt}

and

<foreach collection="queryItems" separator=" and " item="queryItem" open=" " close=" " >

<choose>

<when test="queryItem.type == 'equal'">

${queryItem.field} = #{queryItem.value}

</when>

</choose>

</foreach>

<if test="orderBy == null">

group by sku_pool_id,item_sku_id

</if>

<if test="orderBy != null">

group by sku_pool_id,item_sku_id,${orderBy} order by ${orderBy} ${orderAd}

</if>

<if test="limitEnd != 0">

limit #{limitStart},#{limitEnd}

</if>

</select>

  • 可以看到,在 CK 分页查询时,是通过 limit #{limitStart},#{limitEnd} 实现的分页。

limit 分页方案,在「深翻页」时会存在性能问题。初版方案上线后,在 1000W 量级的底池数据中筛选 10W 的数据,最坏耗时会达到 10s~18s 左右。

三、使用ES Scroll Scan优化深翻页

对于 CK 深翻页时候的性能问题,进行了优化,使用 Elasticsearch 的 scroll scan 翻页方案进行优化。

1、ES的翻页方案

ES 翻页,有下面几种方案:

  • from + size 翻页
  • scroll 翻页
  • scroll scan 翻页
  • search after 翻页

对上述几种翻页方案,查询不同数目的数据,耗时数据如下表。

2、耗时数据

此处,分别使用 Elasticsearch 的 scroll scan 翻页方案、初版中的 CK 翻页方案进行数据查询,对比其耗时数据。

如上测试数据,可以发现,以十万,百万,千万量级的底池为例。

  • 底池量级越大,查询相同的数据量,耗时越大。
  • 查询结果 3W 以下时,ES 性能优;查询结果 5W 以上时,CK 多线程性能优。

四、ES+Hbase组合查询方案

在「使用 ES Scroll Scan 优化深翻页」中,使用 Elasticsearch 的 scroll scan 翻页方案对深翻页问题进行了优化,但在实现时为单线程调用,所以最终测试耗时数据并不是特别理想,和 CK 翻页方案性能差不多。

在调研阶段发现,从底池中取出 10W 的目标数据时,一个商品包含多个字段的信息(CK 表中一行记录有 150 个字段信息),如价格、会员价、学生价、库存、好评率等。对于一行记录,当减少获取字段的个数时,查询耗时会有明显下降。如对 sku1的商品,从之前获取价格、会员价、学生价、亲友价、库存等 100 个字段信息,缩减到只获取价格、库存这两个字段信息。

如下图所示,使用 ES 查询方案,对查询同样条数的场景(从千万级底池中筛选出 7W+ 条数据),获取的每条记录的字段个数从 32 缩减到 17,再缩减到 1个(其实是两个字段,一个是商品唯一标识 sku_id,另一个是 ES 对每条文档记录的 doc_id)时,查询的耗时会从 9.3s 下降到 4.2s,再下降到 2.4s。

从中可以得出如下结论:

  • 一次 ES 查询中,若查询字段和信息较多,fetch 阶段的耗时,远大于 query 阶段的耗时。
  • 一次 ES 查询中,若查询字段和信息较多,通过减少不必要的查询字段,可以显著缩短查询耗时。

下面对结论中涉及的 query 和 fetch 查询阶段进行补充说明。

1、ES查询的两个阶段:query和fetch

在 ES 中,搜索一般包括两个阶段,query 和 fetch 阶段。

  • query 阶段

根据查询条件,确定要取哪些文档(doc),筛选出文档 ID(doc_id)。

  • fetch 阶段

根据 query 阶段返回的文档 ID(doc_id),取出具体的文档(doc)。

2、ES的filesystem cache

1)ES 会将磁盘中的数据自动缓存到 filesystem cache,在内存中查找,提升了速度。

2)若 filesystem cache 无法容纳索引数据文件,则会基于磁盘查找,此时查询速度会明显变慢。

3)若数量两过大,基于「ES 查询的的 query 和 fetch 两个阶段」,可使用 ES + HBase 架构,保证 ES 的数据量小于 filesystem cache,保证查询速度。

3、组合使用Hbase

在上文调研的基础上,发现「减少不必要的查询展示字段」可以明显缩短查询耗时。沿着这个优化思路,参考相关资料设计了一种新的查询方案。

  • ES 仅用于条件筛选,ES 的查询结果仅包含记录的唯一标识 sku_id(其实还包含 ES 为每条文档记录的 doc_id)。
  • Hbase 是列存储数据库,每列数据有一个 rowKey。利用 rowKey 筛选一条记录时,复杂度为 O(1)。(类似于从 HashMap 中根据 key 取 value)。
  • 根据 ES 查询返回的唯一标识 sku_id,作为 Hbase 查询中的 rowKey,在 O(1) 复杂度下获取其他信息字段,如价格,库存等。

使用 ES + Hbase 组合查询方案,在线上进行了小规模的灰度测试。在 1000W 量级的底池数据中筛选 10W 的数据,对比 CK 翻页方案,最坏耗时从 10~18s 优化到了 3~6s 左右。

也应该看到,使用 ES + Hbase 组合查询方案,会增加系统复杂度,同时数据也需要同时存储到 ES 和 Hbase。

五、RediSearch+RedisJSON优化方案

RediSearch 是基于 Redis 构建的分布式全文搜索和聚合引擎,能以极快的速度在 Redis 数据集上执行复杂的搜索查询。RedisJSON 是一个 Redis 模块,在 Redis 中提供 JSON 支持。RedisJSON 可以和 RediSearch 无缝配合,实现索引和查询 JSON 文档。

根据一些参考资料,RediSearch + RedisJSON 可以实现极高的性能,可谓碾压其他 NoSQL 方案。在后续版本迭代中,可考虑使用该方案来进一步优化。

下面给出 RediSearch + RedisJSON 的部分性能数据。

1、RediSearch 性能数据

在同等服务器配置下索引了 560 万个文档 (5.3GB),RediSearch 构建索引的时间为 221 秒,而 Elasticsearch 为 349 秒。RediSearch 比 ES 快了 58%。

数据建立索引后,使用 32 个客户端对两个单词进行检索,RediSearch 的吞吐量达到 12.5K ops/sec,ES 的吞吐量为 3.1K ops/sec,RediSearch 比ES 要快 4 倍。同时,RediSearch 的延迟为 8ms,而 ES 为 10ms,RediSearch 延迟稍微低些。

2、RedisJSON 性能数据

根据官网的性能测试报告,RedisJson + RedisSearch 可谓碾压其他 NoSQL。

  • 对于隔离写入(isolated writes),RedisJSON 比 MongoDB 快 5.4 倍,比 ES 快 200 倍以上。
  • 对于隔离读取(isolated reads),RedisJSON 比 MongoDB 快 12.7 倍,比 ES 快 500 倍以上。

在混合工作负载场景中,实时更新不会影响 RedisJSON 的搜索和读取性能,而 ES 会受到影响。

  • RedisJSON 支持的操作数/秒比 MongoDB 高约 50 倍,比 ES 高 7 倍/秒。
  • RedisJSON 的延迟比 MongoDB 低约 90 倍,比 ES 低 23.7 倍。

此外,RedisJSON 的读取、写入和负载搜索延迟,在更高的百分位数中远比 ES 和 MongoDB 稳定。当增加写入比率时,RedisJSON 还能处理越来越高的整体吞吐量。而当写入比率增加时,ES 会降低它可以处理的整体吞吐量。

总结

本文从一个业务诉求触发,对「千万量级数据中查询 10W 量级的数据」介绍了不同的设计方案。对于「在 1000W 量级的底池数据中筛选 10W 的数据」的场景,不同方案的耗时如下:

  • 多线程 + CK 翻页方案,最坏耗时为 10s~18s。
  • 单线程 + ES scroll scan 深翻页方案,相比 CK 方案,并未见到明显优化。
  • ES + Hbase 组合方案,最坏耗时优化到了 3s~6s。
  • RediSearch + RedisJSON 组合方案,后续会实测该方案的耗时。

>>>>参考资料

  • ES翻页优化和性能优化 | 掘金
  • ES 亿级数据检索优化,三秒返回突破性能瓶颈 | InfoQ
  • RedisJson 横空出世,性能碾压 ES 和 Mongo | 掘金

作者丨变速风声

来源丨网址:

https://juejin.cn/post/7104090532015505416

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn



Tags:数据查询   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
SQL Server 百万数据查询优化技巧三十则
互联网时代的进程越走越深,使用MySQL的人也越来越多,关于MySQL的数据库优化指南很多,而关于SQL SERVER的T-SQL优化指南看上去比较少,近期有学习SQLSERVER的同学问到SQL SERVER数...【详细内容】
2023-11-28  Search: 数据查询  点击:(340)  评论:(0)  加入收藏
微信海量数据查询如何从1000ms降到100ms?
导读微信的多维指标监控平台,具备自定义维度、指标的监控能力,主要服务于用户自定义监控。作为框架级监控的补充,它承载着聚合前 45亿/min、4万亿/天的数据量。当前,针对数据层...【详细内容】
2023-06-01  Search: 数据查询  点击:(320)  评论:(0)  加入收藏
Oracle数据查询和操作策略:优化数据管理的秘籍
当涉及到 Oracle 数据库的数据查询和操作时,有几个基本的概念和语句需要了解。下面将详细解释每个方面,并提供示例代码。 使用 SELECT 语句进行基本查询: SELECT 语句是查询数...【详细内容】
2023-05-20  Search: 数据查询  点击:(60)  评论:(0)  加入收藏
比Hive快十倍的大数据查询利器,你知道吗?
目前最流行的大数据查询引擎非hive莫属,它是基于MR的类SQL查询工具,会把输入的查询SQL解释为MapReduce,能极大的降低使用大数据查询的门槛, 让一般的业务人员也可以直接对大数据...【详细内容】
2023-03-07  Search: 数据查询  点击:(204)  评论:(0)  加入收藏
MySQL千万级数据查询的优化技巧及思路
随着数据量的不断增长,MySQL千万级数据查询的优化问题也日益引人注目。在这篇文章中,我们将深入探讨MySQL千万级数据查询优化的方法和技巧,以帮助开发者更好地优化MySQL性能。...【详细内容】
2023-02-25  Search: 数据查询  点击:(146)  评论:(0)  加入收藏
面对千万级数据查询,CK、ES、RediSearch谁才是王炸?
前言在开发中遇到一个业务诉求,需要在千万量级的底池数据中筛选出不超过 10W 的数据,并根据配置的权重规则进行排序、打散(如同一个类目下的商品数据不能连续出现 3 次)。下面对...【详细内容】
2022-09-08  Search: 数据查询  点击:(391)  评论:(0)  加入收藏
3000字详解Pandas数据查询,建议收藏
作者:俊欣来源:关于数据分析与可视化大家好,又是新的一周,也是2021年的最后一周,今天小编来和大家说一说怎么从DataFrame数据集中筛选符合指定条件的数据,希望会对读者朋友有所帮...【详细内容】
2021-12-30  Search: 数据查询  点击:(245)  评论:(0)  加入收藏
分布式SQL大数据查询引擎的发展
基于SQL的查询引擎简介,包括指向数据仓库和数据湖的链接> Photo by NASA on Unsplash介绍从高层的角度来看,许多数据和分析解决方案已经以相同的方式构建了许多年。 简而言之,...【详细内容】
2020-11-26  Search: 数据查询  点击:(404)  评论:(0)  加入收藏
万亿条数据查询如何做到毫秒级响应?
知乎,在古典中文中意为“你知道吗?”,它是中国的 Quora,一个问答网站,其中各种问题由用户社区创建,回答,编辑和组织。作为中国最大的知识共享平台,我们目前拥有 2.2 亿注册用户,3000...【详细内容】
2020-08-03  Search: 数据查询  点击:(328)  评论:(0)  加入收藏
各行业大数据查询平台,总有用的上的时候
一、数据平台(5类)网络趋势分析6个1、5118 / chinaz&mdash;&mdash;主要用户:SEO专员支持查询网站排名及发展趋势、百度收录情况等信息 2、艾瑞指数&mdash;&mdash;主要用户:互联...【详细内容】
2020-07-01  Search: 数据查询  点击:(3375)  评论:(0)  加入收藏
▌简易百科推荐
向量数据库落地实践
本文基于京东内部向量数据库vearch进行实践。Vearch 是对大规模深度学习向量进行高性能相似搜索的弹性分布式系统。详见: https://github.com/vearch/zh_docs/blob/v3.3.X/do...【详细内容】
2024-04-03  京东云开发者    Tags:向量数据库   点击:(5)  评论:(0)  加入收藏
原来 SQL 函数是可以内联的!
介绍在某些情况下,SQL 函数(即指定LANGUAGE SQL)会将其函数体内联到调用它的查询中,而不是直接调用。这可以带来显著的性能提升,因为函数体可以暴露给调用查询的规划器,从而规划器...【详细内容】
2024-04-03  红石PG  微信公众号  Tags:SQL 函数   点击:(5)  评论:(0)  加入收藏
如何正确选择NoSQL数据库
译者 | 陈峻审校 | 重楼Allied Market Research最近发布的一份报告指出,业界对于NoSQL数据库的需求正在持续上升。2022年,全球NoSQL市场的销售额已达73亿美元,预计到2032年将达...【详细内容】
2024-03-28    51CTO  Tags:NoSQL   点击:(14)  评论:(0)  加入收藏
为什么数据库连接池不采用 IO 多路复用?
这是一个非常好的问题。IO多路复用被视为是非常好的性能助力器。但是一般我们在使用DB时,还是经常性采用c3p0,tomcat connection pool等技术来与DB连接,哪怕整个程序已经变成以...【详细内容】
2024-03-27  dbaplus社群    Tags:数据库连接池   点击:(14)  评论:(0)  加入收藏
八个常见的数据可视化错误以及如何避免它们
在当今以数据驱动为主导的世界里,清晰且具有洞察力的数据可视化至关重要。然而,在创建数据可视化时很容易犯错误,这可能导致对数据的错误解读。本文将探讨一些常见的糟糕数据可...【详细内容】
2024-03-26  DeepHub IMBA  微信公众号  Tags:数据可视化   点击:(7)  评论:(0)  加入收藏
到底有没有必要分库分表,如何考量的
关于是否需要进行分库分表,可以根据以下考量因素来决定: 数据量和负载:如果数据量巨大且负载压力较大,单一库单一表可能无法满足性能需求,考虑分库分表。 数据增长:预估数据增长...【详细内容】
2024-03-20  码上遇见你  微信公众号  Tags:分库分表   点击:(15)  评论:(0)  加入收藏
在 SQL 中写了 in 和 not in,技术总监说要炒了我……
WHY?IN 和 NOT IN 是比较常用的关键字,为什么要尽量避免呢?1、效率低项目中遇到这么个情况:t1表 和 t2表 都是150w条数据,600M的样子,都不算大。但是这样一句查询 &darr;select *...【详细内容】
2024-03-18  dbaplus社群    Tags:SQL   点击:(6)  评论:(0)  加入收藏
应对慢SQL的致胜法宝:7大实例剖析+优化原则
大促备战,最大的隐患项之一就是慢SQL,对于服务平稳运行带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,在日常开发中如何避免出现慢SQL,出现了慢SQL应该按照什...【详细内容】
2024-03-14  京东云开发者    Tags:慢SQL   点击:(5)  评论:(0)  加入收藏
过去一年,我看到了数据库领域的十大发展趋势
作者 | 朱洁策划 | 李冬梅过去一年,行业信心跌至冰点2022 年中,红衫的一篇《适应与忍耐》的报告,对公司经营提出了预警,让各个公司保持现金流,重整团队,想办法增加盈利。这篇报告...【详细内容】
2024-03-12    InfoQ  Tags:数据库   点击:(32)  评论:(0)  加入收藏
SQL优化的七个方法,你会哪个?
一、插入数据优化 普通插入:在平时我们执行insert语句的时候,可能都是一条一条数据插入进去的,就像下面这样。INSERT INTO `department` VALUES(1, &#39;研发部(RD)&#39;, &#39...【详细内容】
2024-03-07  程序员恰恰  微信公众号  Tags:SQL优化   点击:(20)  评论:(0)  加入收藏
站内最新
站内热门
站内头条