微服务场景下如何解决跨实体的关联查询问题

Posted by 无限可能的想象力 on December 11, 2021

为什么需要跨业务的关联查询

在领域建模中,每个微服务负责某些独立实体的实现。微服务之间可以通过HTTP、RPC进行通信,也可以通过消息队列进行异步通信。由于业务需求,有些场景需要多个实体进行关联查询。

关联查询的场景包括:

  • 基于某个维度的数据查询,比如基于终端维度的防火墙日志记录
  • 实体之间进行关联查询

对于第一种场景,可以将某个维度相关的数据构造成一张宽表。 对于第二种场景,可以实现了一个聚合服务,负责同步来自业务的数据到同一个数据库中,由聚合服务提供关联查询的能力。

MySQL如何执行关联查询

在MySQL,每个查询都是一次关联。

MySQL关联执行的策略很简单:MySQL对任何关联都执行嵌套循环关联操作,即MySQL先在一个表中循环取出单条数据,然后再嵌套循环到下一个表中寻找匹配的行,依次下去,直到找到所有表中匹配的行为止。然后根据各个表匹配的行,返回查询中需要的各个列。MySQL会尝试在最后一个关联表中找到所有匹配的行,如果最后一个关联表无法找到更多的行以后,MySQL返回到上一层的关联表,看是否能够找到更多的匹配记录,依次类推迭代执行。

优化关联查询的一些技巧:

  • 确保ON或者USING子句的列上有索引
  • 确保任何的 GROUP BY 和 ORDER BY 中的表达式只涉及到一个表中的列,这样MySQL才有可能使用索引来优化

MySQL基于嵌套关联查询还进行了一些优化:MRR、基于块的嵌套关联查询。

MongoDB如何执行关联查询

MongoDB 通过 $lookup 语法来支持关联查询。$lookup在同一个数据库中未分片集合上执行左连接,从join后的集合中过滤文档并进行处理。

Elasticsearch如何执行关联查询

Elasticsearch并没有对处理实体之间的关系给出直接的方法。Elasticsearch中进行关系型数据管理的4种常用方法:

  • Application-side joins
  • Data denormalization:存在部分冗余数据
  • Nested objects
  • Parent/child relationships

Application-side joins能够与底层的数据存储解耦,具有更好的可扩展性。然而,多次单表查询会增加网络通信开销,导致单次请求的通信响应时间变长。

总结

MySQL的join是在sql解析层执行的,而存储引擎只是进行了基础的数据查询。

要想实现跨业务的关联查询,实际上要做的工作也就是MySQL的join能力在应用层进行实现以及优化。