假设我有两个表:
Group
(
id integer primary key,
someData1 text,
someData2 text
)
GroupMember
(
id integer primary key,
group_id foreign key to Group.id,
someData text
)
我知道我的SQL语法不正确:)希望足够清楚。我的问题是:我想加载一个组记录和与该组关联的所有GroupMember记录。我认为,有两种选择。
单个查询:
SELECT Group.id, Group.someData1, Group.someData2 GroupMember.id, GroupMember.someData
FROM Group INNER JOIN GroupMember ...
WHERE Group.id = 4;
两个问题:
SELECT id, someData2, someData2
FROM Group
WHERE id = 4;
SELECT id, someData
FROM GroupMember
WHERE group_id = 4;
第一个解决方案的优点是只有一个数据库往返,但缺点是返回冗余数据(所有组数据都为每个组成员重复)
第二个解决方案不会返回任何重复数据,但需要两次往返数据库。
这里最好的是什么?我想有一些阈值,如果组大小变得足够大,返回所有冗余数据的成本将大于额外数据库调用所涉及的开销。我应该在这里考虑其他什么?
谢谢, 约旦
答案 0 :(得分:3)
如果您确实希望结果加入,我相信在服务器级别进行加入总是更有效率。 SQL处理器旨在匹配数据集。 如果你真的想要2个sql语句的结果,你总是可以在一个批处理中用分号分隔两个语句,并通过一次往返DB获得两个结果集。
答案 1 :(得分:2)
如何最终使用数据是一个重要且未知的因素。
我建议大多数应用程序使用单一查询方法。正确的索引将使查询比两种查询方法更有效。
如果您需要选择多个组,单个查询方法还具有保持有效的优势。
答案 2 :(得分:1)
如果您只是要将每个请求转发到数据库中的单个组记录,那么我将使用第二个选项。如果要检索多个组记录和关联的组成员记录,请使用连接,因为它会更快。
答案 3 :(得分:0)
通常,它取决于您尝试显示的数据类型。
如果您要显示单个组及其所有成员,则两个选项之间的性能差异可以忽略不计。
如果您要显示许多组及其所有成员,那么必须为每个连续组进行数据包往返的开销将很快超过您从接收少量数据获得的任何好处。
您在推理中可能需要考虑的其他一些事情
结果集大小 - 对于许多组和成员,您的结果集大小可能会成为限制因素,因为要检索并将其保留在内存中的大小会增加。第二种选择可能会发生这种情况。您可能需要考虑分页数据,这样您一次只能检索某个子集。
延迟加载 - 如果您只获取某些组的成员,或者用户一次请求成员一组,请考虑延迟加载。这意味着仅在需要时进行附加查询以获取组的成员。这仅在某些用例中有意义,但它比预先检索所有数据更有效。
答案 4 :(得分:0)
根据数据库和前端应用程序的类型,您可以在一次旅行中返回两个SQL语句的结果(例如,SQL Server 2005中的存储过程)。
如果您要创建一个需要Group表中的许多字段的报表,您可能不希望第一个查询中的数据量增加。
如果这是某种类型的数据输入应用程序,您可能已经将组数据呈现给用户,因此他们可以在where子句上填充组ID(或者最好通过某些参数),现在他们需要成员结果。
答案 5 :(得分:0)
这真的,真的,真的取决于你对数据的用处。
如果您正在组装一个邮件组的成员列表,并且您需要为要发送给成员的每个字母的组名,并且您没有使用组级别,那么单个连接查询很有意义。
但是,如果您正在编写主 - 详细信息屏幕或报告,每个组的页面以及在组和成员级别显示信息,则两个单独的查询可能最有用。
除非你要检索大量的数据(成千上万的群体,每组有数百个成员,或类似的数量级),否则你不太可能看到这两种方法的表现之间存在很大差异。
答案 6 :(得分:-2)
在像这样的简单查询中,我会尝试在一个查询中执行它。两个数据库调用的开销可能会超过查询的额外SQL处理时间。
UNION子句将为您执行此操作:
SELECT id, someData1, someData2
FROM Group
WHERE id = 4
UNION
SELECT id, someData, null
FROM GroupMember
WHERE group_id = 4;