首页 > 解决方案 > 查询任意相关表时的 JOIN 与 SELECT IN

问题描述

从多个表中提取数据以映射到 GraphQL 结果时,哪个更有效?

伪代码如下。

版本 1 - 将 N 个表连接在一起并将它们解析为调用方的单独对象

alldata = SELECT a.*, b.*, c.*
    FROM aaaa a
    LEFT OUTER JOIN bbbb b on a.id = b.parent_id
    LEFT OUTER JOIN cccc c on b.id = c.parent_id
    WHERE a.name = 'my name';
/* Map flat DB rows to Java pojo-s */
aObj = parseRowsIntoJavaObjects(alldata)

版本 2 - 对表 1 逐个执行选择,通过父行 id-s 限制它们

a_rows = SELECT a.* FROM aaaa a WHERE a.name = 'my name';
b_rows = SELECT b.* FROM bbbb b WHERE b.parent_id IN (a_rows.id);
c_rows = SELECT c.* FROM cccc c WHERE c.parent_id IN (b_rows.id);
/* Map flat DB rows to Java pojo-s */
bObj = parseRowsIntoJavaObjects(b_rows, c_rows);
aObj = parseRowsIntoJavaObjects(a_rows, bObj);

这些表使用外键连接,并且可以具有 1:1、1:N 和 N:N 关系。否则它们的结构没有定义——解决方案必须针对任意数据模型。可以根据需要添加索引,并且可以假定存在任何必要的索引来执行查询。

询问是因为可以有任意数量的表以这种方式连接,我担心版本 1是否会导致由于多对一关系起作用而不得不在多行中多次返回相同数据的问题。

我知道如果事情可以用一个来管理并且 IN() 不是特别快,那么进行多个查询通常是一个坏主意。在这里使用 IN 仍然是一个坏主意吗?

由于该解决方案必须是通用的并适用于任意数量的数据模型,因此我不想像大多数处理 JOIN...WHERE IN().. 的问题一样尝试并针对特定模型对其进行优化。我想请教一下从任意层次结构加载关系数据的一般性能更高的方法是什么,直到……说 3 级深?

我在 SO 上发现的唯一一种匹配问题处理了一个略有不同的案例,但在其答案中提倡两种有些相似的解决方案:从多个表中选择 - 一对多关系

数据库:MariaDB

标签: mysqlsqldatabasedatabase-designmariadb

解决方案


评论太长了。

但是,您应该以应用程序中需要的格式提取数据。如果你想在 Java 中为 As、Bs 和 Cs 提供三个不同的对象,那么拉取数据 3 次。如果您想要一个组合来自表的属性的单个对象,则使用单个查询与JOIN.

您的描述说您需要单独的对象,因此请使用单独的查询。你真的需要在 SQL 中,因为一个查询只能返回一组列。

在这种情况下,第一种方法有缺点。一个是每行的大小——每行包含 B 和 C 的列。即使值是 ,这也会占用空间NULL

更大的缺点是结果的倍增。如果 A 中的给定行在 B 中有 10 个匹配项,在 C 中有 20 个匹配项,那么您的查询将为该值返回 200 行。然后,您将不得不在应用程序端进行大量重复数据删除。

运行多个查询有一个小的缺点——运行和编译查询以及返回多个数据集的开销。我不会担心这一点,因为三个单独的查询更适合您想要完成的任务。


推荐阅读