瞎扯淡 解决搜索问题就一定要上 ElasticSearch 吗?

lanzhiheng · 2023年02月18日 · 最后由 fleam 回复于 2023年03月25日 · 1666 次阅读

我们总想寻找锤子来处理眼前的这个钉子,然而,说不定这里压根就不需要用到钉子呢。原文链接:https://step-by-step.tech/posts/huiliu-simple-solution-for-searching

事情是这样的

回流是传统行业麾下的一款互联网产品。正常情况下,数据量会逐渐增大,但是膨胀速度并不会说特别快。然而,只要有足够的时间,数据量总会到达一定程度。此时系统的某些部分就会渐渐变得缓慢,有些查询的速度会变得不忍直视。

回流是有自己的管理端的(基于 React),当时是为了让自己人可以舒服一点,用空闲时间孵化的一个项目。无论是可扩展性还是交互体验应该会比ActiveAdmin强不少。只不过投入的精力有限,还有很大的优化空间。万万没想到,近期的性能问题就出在管理端。同事们映有时候加载一个列表页面需要 5s 左右的时间,几乎是处于一个不可用的状态。

后来发现,归根结底还是数据查询(搜索)不够快拖慢了整个请求,毕竟数据量摆在那里。

> Backflow.search_by_admin('订单号').order('backflows.received_at DESC')
  Backflow Load (2838ms)  SELECT "backflows".* FROM "backflows" LEFT OUTER JOIN "goods" ON "goods"."backflow_id" = "backflows"."id" LEFT OUTER JOIN "logis.....
=> #<ActiveRecord::Relation []>
irb(main):003:0> Backflow.count
   (55.9ms)  SELECT COUNT(*) FROM "backflows"
=> 332690

在 30w 条数据中,要在联表的情况下做模糊查找并排序,一次操作要花费2838ms,也难怪一个页面要加载好几秒的时间(业务团队居然忍了很长一段时间都不反馈过来)。作为一个技术宅,脑海中下意识就浮现出好几种解决方案

  1. 添加合适的索引(感觉索引能治百病)。
  2. 优化查询条件,看情况引入数据库全文搜索。
  3. 引入ElasticSearch这种主流的搜索解决方案。

下意识地想要一步到位地选择方案 3,由于对接下来要做的事情很有信心,便告知团队,即将要用酷炫的搜索引擎技术来优化整个站点的搜索体验了。

你真的需要那么多数据吗?

在笔者疯狂调研全文搜索引擎的时候,有一天业务团队被卡到不行了,问我啥时候能优化好,因为实在是影响工作效率。要上ElasticSearch并不是那么容易的事情,却无法跟大伙解释这点,他们能看到的就只是系统卡不卡,才不管优化难度大不大呢。

考虑到业务团队在日常货品上架的过程中最常操作的就是最新的一些订单,绝大多数情况下其实也没必要从所有历史数据中进行搜索。于是做了个应急优化搜索范围限制在最近一个月,要是遇到搜索不到的情况,再联系笔者帮忙寻找对应的订单,而且这种情况应该极少。然而就在交代这些的时候,笔者突然灵机一动。

为何要执着于优化全局范围内的搜索性能呢,上架部门顶多就只需要几个月范围内的数据。一定有更简单的解决方案。

最后选择了如下解决方案:

  1. 管理端限制筛选范围,默认只显示最近两周的数据,默认搜索范围也是两周。
  2. 如果搜索无果,同事们可以选择更早之前的时间段做进一步的查找,但时间范围的长度不得超过一个月,以免数据太多造成卡顿。
  3. 多往前翻几个月没有数据就基本可以判定用户近期没有下过对应的订单,可以引导用户先做下单操作。

这并不是什么了不起的优化手段,也没有引入新的技术,不过对于后台管理软件来说已经足够用了。只不过是默认限制了一下时间范围而已,改动小,带来的效益却很大。默认搜索条件能满足 80% 以上的场景了,搜索性能提高了 10 倍不止。

我们总会下意识地寻求更新更酷炫的技术来解决眼下的问题,然而大多数的情况下远水难救近火。结合实际的场景,说不定会有虽看起来朴实无华,但是却更简单实用的解决方案。

路漫漫

笔者这次的优化,放在后台场景是十分合适的,优化效果也很好。然而,如果放在 App 端就不一定了,毕竟 App 的用户多,搜索需求大,限制了搜索范围,很难满足大部分人的要求。在 App 端的搜索接口,还真的要考虑用全文搜索的解决方案呢。笔者也会继续对ElasticSearch做调研。

只有职位够高才有机会在需求层面就解决问题呀😄

能在需求和设计层面解决、缓解问题是最好滴。如果客户非要在技术层面去实现,俺们一般就三个字:“得加钱”😈

spike76 回复

😬 是这个理。

用 pg 吧,ruby china 不就这样吗

PG + 分词 就很够用了

机器什么配置?PG 还是 MySQL?

深有同感:我们公司有很多搜索业务,数据存放在 MySQL 中,我使用 LIKE "%关键词%"进行搜索,并使用 LEN(关键词) 进行排序,按理这搜索的结果,是很符合用户的需求的。但是 LIKE 走不了索引呀,所以搜索时间巨慢。最好的方式还是放在 ES 中。没办法,我的职位太低,平时问个需求还要挨吵呢,所以这个功能只能这样了。。。

哈哈,我们用了 ElasticSearch 😅

可以用轻量级的搜索引擎,如 meilisearch https://www.meilisearch.com/

Rei 回复

感谢!确实没了解过 MySQL 全文搜索,我要看一下这方面的内容了

后台的搜索其实不需要全文检索,只需要 like 匹配,再加个索引就可以了,pg 的 like 是可以加索引的

👍 需求需要技术支撑,有的时候,需求在现有的情况下,不那么合理,就需要需求让步。所谓的 trade-off。

选用 ES 一个主要原因是性能。数据库 like 扛不住了,或者不想影响其他查询太多,所以才上 ES。ES 简单的找找文档就能搞定,真正优化什么的,就需要深入研究。

技术影响需求,到了一定阈值,甚至决定了需求。比如延迟超过 10s,这个就不仅仅是技术问题,而是需求问题了。

需要通过机器学习归纳

hooopo 回复

😂 主要是搜索依赖的字段太多,索引维护起来有点费劲呢。

wikimo 回复

😂 我也准备用了,有空跟你取取经。

我是打算,

  1. 后台业务就继续保持现状,可能会像 @hooopo 所说的看情况针对 LIKE 搜索加索引。
  2. App 端业务的所有搜索都依赖 ES 了。客户体验应该会好很多。
Peter 回复

請問這個有支持中文嗎?

【【IT 老齐 160】1000 万卡数据从 3 秒提升干到 21 毫秒,150 倍!我们如何利用 bitmap 优化工行储蓄卡业务 - 哔哩哔哩】 https://b23.tv/KapqTAQ 可以参考一下这个

eGluZl 回复

meilisearch +1, 轻量好用

meilisearch 跟 elasticsearch 相比起来有什么优缺点么?

自己搜了一下: Meilisearch 和 Elasticsearch 都是基于 JSON 的全文搜索引擎,但它们有一些不同的特点和适用场景。根据搜索结果 123,我总结了以下几点:

Meilisearch 是一个轻量级的搜索引擎,使用 Rust 语言编写,不依赖 JVM 或其他运行时环境。Elasticsearch 是一个复杂的搜索引擎,使用 Java 语言编写,基于 Lucene 库,需要 JVM 运行。 Meilisearch 提供了开箱即用的功能,如错字容忍、过滤器和同义词。Elasticsearch 需要更多的配置和训练才能实现这些功能。 Meilisearch 更适合中小型数据集(少于五百万条记录)和简单的搜索需求。Elasticsearch 更适合大型数据集(达到 PB 级别)和复杂的搜索和聚合需求。 Meilisearch 只支持单节点部署,不具备高可用性和容错性。Elasticsearch 支持多节点集群部署,具备水平扩展和分布式处理能力。 Meilisearch 是完全开源的软件,可以自由使用和修改。Elasticsearch 是源可见的软件,遵循 SSPL 协议,在某些情况下需要付费使用。

could just use sql to search?

分词加二级索引

需要 登录 后方可回复, 如果你还没有账号请 注册新账号