真正的问题是:这些记录是一对一关系还是一对多关系?
TLDR 答案:
如果是一对一的,请使用JOIN 语句。
如果是一对多,则使用一个(或多个)SELECT 语句进行服务器端代码优化。
为什么以及如何使用 SELECT 进行优化
SELECT'ing(使用多个查询而不是连接)基于一对多关系对大量记录产生最佳效率,因为JOIN'ing 存在指数内存泄漏问题。抓取所有数据,然后使用服务器端脚本语言对其进行整理:
SELECT * FROM Address WHERE Personid IN(1,2,3);
结果:
Address.id : 1 // First person and their address
Address.Personid : 1
Address.City : "Boston"
Address.id : 2 // First person's second address
Address.Personid : 1
Address.City : "New York"
Address.id : 3 // Second person's address
Address.Personid : 2
Address.City : "Barcelona"
在这里,我在一个 select 语句中获取所有记录。这比JOIN 好,后者将一次获取一小组这些记录,作为另一个查询的子组件。然后我用看起来像...的服务器端代码解析它。
<?php
foreach($addresses as $address) {
$persons[$address['Personid']]->Address[] = $address;
}
?>
何时不使用 JOIN 进行优化
JOIN'基于与单个记录的一对一关系对一大组记录进行处理,与多个SELECT 语句相比,一个接一个地获得最佳效率,后者只需获取下一个记录类型.
但是JOIN 在获取具有一对多关系的记录时效率很低。
示例:数据库 Blogs 有 3 个感兴趣的表,Blogpost、Tag 和 Comment。
SELECT * from BlogPost
LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id
LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id;
如果有 1 篇博文、2 个标签和 2 个 cmets,您将得到如下结果:
Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag2, comment1,
Row4: tag2, comment2,
注意每条记录是如何复制的。好的,所以,2 cmets 和 2 tags 是 4 行。如果我们有 4 个 cmets 和 4 个标签怎么办?不是 8 行,而是 16 行:
Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag1, comment3,
Row4: tag1, comment4,
Row5: tag2, comment1,
Row6: tag2, comment2,
Row7: tag2, comment3,
Row8: tag2, comment4,
Row9: tag3, comment1,
Row10: tag3, comment2,
Row11: tag3, comment3,
Row12: tag3, comment4,
Row13: tag4, comment1,
Row14: tag4, comment2,
Row15: tag4, comment3,
Row16: tag4, comment4,
添加更多的表、更多的记录等,问题将迅速膨胀到数百行,这些行都充满了大部分冗余数据。
这些重复的成本是多少?内存(在 SQL 服务器和尝试删除重复项的代码中)和网络资源(在 SQL 服务器和您的代码服务器之间)。
来源:https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html