缓慢的 SQL 查询正在扼杀你的推荐引擎

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

在当今快节奏的世界中,用户不会等待您的推荐引擎查询数据库几分钟。

事实上,如果他们愿意多等几秒钟,那你就很幸运了。

接下来的问题是:您的关系数据库是否以向您的用户提供相关且有见地的建议所需的速度运行?否则,您的慢速 SQL 查询可能是罪魁祸首。

在这个关于 SQL 压力 的系列中,我们将深入探讨关系数据库 (RDBMS) 性能问题的原因和解决方法,包括面向未来的 图形数据库 替代方案。

之前,我们介绍了 SQL 压力的五个确定迹象 以及 RDBMS 和图形数据库模型之间的比较 。本周,我们将深入研究推荐引擎的具体示例,并在数据建模和编写查询方面将关系数据库与图形数据库进行比较。

关系数据库与图形数据库中的数据建模

在关系数据库中,简单 推荐引擎 的数据建模需要创建多个表。您将为客户、订单和产品创建单独的表,以及表示哪些客户在哪个订单中购买了哪些产品的中间 JOIN 表。

相比之下, 图形数据库的数据模型 可以很容易地在餐巾背面勾画出来。客户购买了某种产品。客户与产品的关系作为存储订单的一部分进行存储。其他客户可能购买了相同的产品。

使用这个简单的数据库模型,您可以轻松地问“这些人还购买了哪些其他产品?”

使用图形数据库为推荐引擎建模是白板友好的。它不仅对开发人员来说很直观,而且对每个熟悉业务领域的人来说都是直观的。

换句话说,对于图数据库,逻辑模型——我们思考问题的方式——对应于物理模型——数据库存储、查询和可视化数据的方式。

对于当今人们面临的许多有趣的数据问题——尤其 是构建相关的推荐引擎 ——仅仅知道两个实体(产品、用户、评级、评论等)是相关联的是不够的。毕竟,关系数据库可以告诉我们很多。

了解这些 数据连接 也很重要:它们的含义、重要性以及它们的强度、重量或质量。在我们的推荐引擎示例中,这些可能是这样的问题,哪些产品是相关的,这种关系的强度是多少?哪些用户对特定产品留下了高质量(或低质量)的评论?有多少朋友的朋友购买了类似的产品?

功能齐全的图形数据库可以回答这些类型的数据关系问题,使您能够合并有关这些连接的特征或强度的相关信息。

SQL 查询与。图数据库查询

与关系 SQL 查询不同,图形数据库查询易于编写和理解。

图形数据库通常有自己的查询语法。在 Neo4j 的情况下,此语法由一种称为 Cypher 的简单但富有表现力的语言控制,该语言专为遍历数据关系而构建。

Cypher 查询比 SQL 查询简单得多。事实上,在 Cypher 中,一个长的 SQL 查询经常可以被压缩成更少的行。

这是一个假设的推荐引擎的 Cypher 查询示例:


 MATCH (u:Customer {customer_id:’customer-one’})-[:BOUGHT]->(p:Product)<- [:BOUGHT]-(peer:Customer)-[:BOUGHT]->(reco:Product) 
WHERE not (u)-[:BOUGHT]->(reco) 
RETURN reco as Recommendation, count(*) as Frequency 
ORDER BY Frequency DESC LIMIT 5;

这个 Cypher 查询表示,对于每个购买产品的客户,推荐引擎应该查看同行客户购买的产品,然后将它们推荐给当前用户。 WHERE 子句删除客户已经购买的产品,因为我们不想推荐客户已经购买的产品。

Cypher 查询的 MATCH 子句中的每个箭头表示一个关系,该关系将被建模为关系模型中的多对多 JOIN 表,每个表有两个 JOIN。因此,即使是这个简单的查询也包含六个跨表的 JOIN。

下面是等效的 SQL 查询:


 MATCH (u:Customer {customer_id:’customer-one’})-[:BOUGHT]->(p:Product)<- [:BOUGHT]-(peer:Customer)-[:BOUGHT]->(reco:Product) 
WHERE not (u)-[:BOUGHT]->(reco) 
RETURN reco as Recommendation, count(*) as Frequency 
ORDER BY Frequency DESC LIMIT 5;

由于 JOIN 的复杂性,这个 SQL 查询不仅会遇到性能问题 ,而且随着给定数据集变大,它的性能也会降低。在构建推荐引擎时,这种性能水平是 无法接受的

如果您的推荐引擎由关系数据库提供支持,用户将不会等待您的建议加载,即使它们是完全相关的。如果您的用户不愿等待,您的业务就会受到影响。

是时候为工作选择合适的工具了, 将您的推荐引擎转移到图形数据库 ,将数据库查询时间从几分钟缩短到几毫秒。有 这么 快速入门的 方法 ,将图形数据库添加到您的推荐引擎是您可以做出的最佳时间投资。