我最近与另一位开发人员进行了讨论,该开发人员向我声称JOIN(SQL)是无用的。从技术上讲,这是正确的,但他补充说,使用联接比在代码(C#或Java)中发出多个请求和链接表效率低。
对于他来说,加入是针对那些不在乎性能的懒惰的人。这是真的?我们应该避免使用联接吗?
我最近与另一位开发人员进行了讨论,该开发人员向我声称JOIN(SQL)是无用的。从技术上讲,这是正确的,但他补充说,使用联接比在代码(C#或Java)中发出多个请求和链接表效率低。
对于他来说,加入是针对那些不在乎性能的懒惰的人。这是真的?我们应该避免使用联接吗?
Answers:
不,我们应该避免持有如此难以置信的错误观点的开发人员。
在许多情况下,数据库联接比通过客户端执行的任何操作快几个数量级,因为它避免了数据库往返,并且数据库可以使用索引来执行联接。
我什至无法想像一种情况,正确使用联接会比等效的客户端操作慢。
编辑:在某些罕见的情况下,自定义客户端代码比直接的数据库联接可以更有效地执行操作(请参阅meriton的评论)。但这是非常例外。
在我看来,您的同事最好使用no-sql文档数据库或键值存储。它们本身就是非常好的工具,非常适合许多问题。
但是,关系数据库已针对使用集进行了优化。有基于连接的是查询数据的很多,很多方面远远超过许多往返的效率更高。这是rdbms的多功能性来自何处。您也可以在nosql存储区中实现相同的功能,但是您通常最终会构建一个单独的结构以适合每种不同的查询性质。
简而言之:我不同意。在RDBMS中,联接是基本的。如果不使用它们,则不会将其用作RDBMS。
好吧,他在一般情况下是错误的。
在优化程序提示,表索引,外键关系以及其他可能的数据库供应商特定信息的帮助下,数据库能够使用多种方法进行优化。
不,你不应该。
数据库是专门为处理数据集而设计的(显然。。。)。因此,他们在执行此操作时效率极高。通过在他自己的代码中进行本质上是手动联接的工作,他正试图接管专门为这项工作设计的角色。他的代码与数据库中的代码一样高效的机会非常渺茫。
顺便说一句,没有连接,使用数据库有什么意义?他可能还只是使用文本文件。
如果将“懒惰”定义为希望编写更少代码的人,那么我同意。我同意,如果将“懒惰”定义为希望拥有工具的人去做自己擅长的事情。因此,如果他只是同意Larry Wall(关于优秀程序员的属性),那么我也同意他的观点。
嗯,联接是关系数据库如何将表彼此关联。我不确定他在说什么。
如何多次调用数据库比一次调用更有效率?加上sql引擎在执行此类操作方面已进行了优化。
也许您的同事懒得学习SQL。
是的你应该。
而且由于性能,您应该使用C ++而不是C#。C#适用于懒惰的人。
不不不。由于性能原因,应使用C而不是C ++。C ++适用于懒惰的人。
不不不。由于性能原因,应使用汇编而不是C。C是懒惰的人。
是的,我在开玩笑。您可以在没有联接的情况下制作速度更快的程序,并且可以在没有联接的情况下使用更少的内存制作程序。但是在许多情况下,开发时间比CPU时间和内存更重要。放弃一点表现,享受生活。不要浪费时间一点点的性能。并告诉他:“为什么不从您的位置到办公室直走高速公路?”
“从技术上讲,这是正确的”-类似地,SQL数据库也没有用:如果使用一个CSV文件并将其关联到代码中就可以得到相同的结果,那么使用一个数据库有什么意义呢?哎呀,任何抽象都适合懒惰的人,让我们回到在硬件上使用机器代码进行编程的方式!;)
而且,除了最复杂的情况之外,他的主张都是不正确的:RDBMS进行了严格的优化,以使JOIN 快速。关系数据库管理系统,对吗?
unnecessary
,而useless
在前面的句子。说联接无用显然是不正确的,不需要考虑任何技术问题。无论如何,操作人员和同事对RDBMS的误解并不罕见:stackoverflow.com/q/5575682/47550
我工作的最后一家公司也不使用SQL连接。相反,他们将这项工作移至旨在水平缩放的应用程序层。此设计的基本原理是避免在数据库层工作。通常,数据库成为瓶颈。它比数据库更容易复制应用程序层。可能还有其他原因。但这是我现在记得的那个。
是的,我同意与数据库连接相比,在应用程序层完成的连接效率低下。网络通讯也更多。
请注意,我对避免SQL连接并没有采取强硬立场。
让我们考虑一个示例:一个带有发票记录的表,以及一个带有发票行项目记录的相关表。考虑客户端伪代码:
for each (invoice in invoices)
let invoiceLines = FindLinesFor(invoice)
...
如果您有100,000个发票,每个发票有10行,则此代码将从100万张表中查找10条发票行,并且将执行100,000次。随着表大小的增加,选择操作的数量会增加,并且每个选择操作的成本也会增加。
如果计算机速度很快,如果您有几千条或更少的记录,您可能不会注意到这两种方法之间的性能差异。因为成本的增加不只是线性的,所以随着记录数量的增加(例如成百万的记录),您将开始注意到差异,并且随着数据集大小的增加,差异将变得难以忍受。
但是加入。将使用表的索引并合并两个数据集。这意味着您有效地扫描了第二张表,而不是随机访问了N次。如果定义了外键,则数据库已经在内部存储了相关记录之间的链接。
想象一下自己做。您有一个按字母顺序排列的学生名单和一个笔记本,其中包含所有学生的成绩报告(每堂课一页)。笔记本按学生姓名的顺序排序,顺序与清单相同。您希望如何进行?
要么:
我怀疑他对于应该使用什么数据库的观点有限。最大化性能的一种方法是将整个数据库读入内存。在这种情况下,您可能会获得更好的性能,并且如果需要提高内存效率,则可能需要执行联接。但是,这实际上并没有使用数据库,而是数据库IMHO。
MEMORY
引擎)。在没有数据库的情况下重新实现数据库功能通常是NIH严重病例的征兆;)
他错了,连接才是合格的程序员所使用的。在某些有限的情况下,他提出的方法更有效(而且我可能会使用Documant数据库),但是如果有大量数据,我将看不到它。例如,使用以下查询:
select t1.field1
from table1 t1
join table2 t2
on t1.id = t2.id
where t1.field2 = 'test'
假设您在表1中有1000万条记录,在表2中有100万条记录。假设表1中有900万条记录满足where子句。假设其中只有15个也位于table2中。您可以运行此sql语句,如果正确建立索引将花费毫秒,并且仅通过1列数据在网络上返回15条记录。或者,您可以通过两列数据发送一千万条记录,并通过网络分别发送另外一百万条带有一列数据的记录,并将它们组合在Web服务器上。
或者,当然,您可以随时将数据库的全部内容保留在Web服务器上,如果您拥有的数据量和不断变化的数据量不多,那就太傻了。如果您不需要关系数据库的质量,请不要使用它。但是,如果这样做,请正确使用它。
除非我被严重误解,否则问题中的逻辑是非常有缺陷的
如果每个A的B中有20行,则A中的1000行意味着B中的2万行。除非B中的表“ AB”很多,其中包含映射的20k行,否则B中不能只有100行。 。
因此,要获取有关100条B行中的哪20条映射到每条A行的所有信息,您还可以表AB。所以这可能是:
因此,当您检查数据时,客户端中的“ JOIN”确实会添加任何值。并不是说这不是一个坏主意。如果我要从数据库中检索一个对象,那么将其分解为单独的结果集更有意义。对于报告类型的调用,我几乎总是将其拼合为一个。
无论如何,我要说这种规模的交叉连接几乎没有用。这是一个糟糕的例子。
您必须在某个地方加入,这就是RDBMS擅长的。我不想与任何认为自己可以做得更好的客户端代码猴子合作。
事后思考:
要加入客户端,需要持久对象,例如DataTables(在.net中)。如果您有一个扁平化的结果集,则可以通过诸如DataReader之类的轻量级对象来使用它。高容量=大量客户端资源用于避免数据库JOIN。