我最近与另一位开发人员进行了讨论,他们向我声称JOIN(SQL)没用。这在技术上是正确的,但他补充说,使用连接比在代码(C#或Java)中创建多个请求和链接表效率低。
对于他来说,加入的是那些不关心表现的懒惰人士。这是真的?我们应该避免使用连接吗?
答案 0 :(得分:187)
不,我们应该避免那些持有这种令人难以置信的错误观点的开发者。
在许多情况下,数据库连接比通过客户端完成的任何操作快几个数量级,因为它避免了数据库往返,并且数据库可以使用索引来执行连接。
在我的脑海中,我甚至无法想象一个正确使用的连接比同等的客户端操作慢的单一场景。
编辑:在极少数情况下,自定义客户端代码可以比简单的数据库连接更有效地执行操作(请参阅meriton的评论)。但这是个例外。
答案 1 :(得分:83)
听起来像你的同事会对一个无sql文档数据库或键值存储做得好。这些本身就是非常好的工具,非常适合许多问题。
但是,关系数据库已经过大量优化,无法使用集合。有许多方法可以根据连接来查询数据,这些连接比大量往返更有效率 。这就是rdbms的多功能性所在。你也可以在nosql商店中实现相同的功能,但是你最终会建立一个适合每种不同查询性质的独立结构。
简而言之:我不同意。在RDBMS中,联接是 基本 。如果您不使用它们,则不会将它用作RDBMS。
答案 2 :(得分:46)
嗯,他在一般情况下是错的。
数据库能够使用各种方法进行优化,这可以通过优化器提示,表索引,外键关系以及可能的其他数据库供应商特定信息来实现。
答案 3 :(得分:24)
数据库专门用于处理数据集(显然......)。因此,他们在这方面非常有效率。通过在他自己的代码中进行基本上手动连接,他试图接管专门为工作设计的东西的角色。他的代码与数据库中的代码一样高效的可能性非常小。
顺便说一下,没有加入,使用数据库的重点是什么?他也可以只使用文本文件。
答案 4 :(得分:19)
如果“懒惰”被定义为想要编写更少代码的人,那么我同意。如果“懒惰”被定义为想要让工具做他们擅长的工作的人,我同意。因此,如果他只是同意Larry Wall(关于优秀程序员的属性),那么我同意他的看法。
答案 5 :(得分:16)
嗯,连接是关系数据库如何将表相互关联的。我不确定他在做什么。
如何对数据库进行多次调用比一次调用更有效?在执行此类操作时,还优化了sql引擎。
也许你的同事懒得学习SQL。
答案 6 :(得分:12)
是的,你应该。
由于性能的原因,您应该使用C ++而不是C#。 C#适合懒人。
不,不,不。由于性能原因,您应该使用C而不是C ++。 C ++适合懒惰的人。
不,不,不。由于性能原因,您应该使用程序集而不是C语言。 C适合懒人。
是的,我在开玩笑。你可以在没有连接的情况下制作更快的程序,你可以使用更少的内存而无需连接。但在许多情况下,您的开发时间比CPU时间和内存更重要。放弃一点表演,享受生活。不要为了一点点的表现而浪费你的时间。并告诉他“你为什么不从你的地方到你的办公室直行高速公路?”
答案 7 :(得分:11)
“这技术上是正确的” - 类似地,SQL数据库是无用的:当你使用一堆CSV文件得到相同的结果并在代码中将它们关联起来时,使用它的重点是什么?哎呀,任何抽象都是为了懒人,让我们回到硬件上的机器代码编程! ;)
此外,除了最复杂的情况之外,他的论点是不真实的:RDBMS经过大量优化,可以使JOIN快速 。 关系数据库管理系统,对吗?
答案 8 :(得分:7)
我工作的最后一家公司也没有使用SQL连接。相反,他们将此工作移至应用层,该应用层旨在水平扩展。此设计的基本原理是避免在数据库层工作。通常数据库成为瓶颈。它比数据库更容易复制应用程序层。可能还有其他原因。但这是我现在可以记得的那个。
是的我同意与数据库完成的连接相比,在应用层完成的连接效率低下。更多的网络通信。
请注意,我并没有采取严厉措施来避免SQL连接。
答案 9 :(得分:5)
我不明白语句“加入SQL是无用的”的逻辑。 在处理数据之前过滤和限制数据是否有用?正如您所做的其他响应者所说,这就是数据库引擎的作用,它应该是他们擅长的。
也许懒惰的程序员会坚持使用他们熟悉的技术,并且出于非技术原因而避免其他可能性。
我留给你决定。
答案 10 :(得分:5)
听起来像是“我可以写得更好”的经典案例。换句话说,他看到了一些他认为是颈部疼痛的东西(在SQL中编写了一堆连接)并且说“我确信我可以写得更好并获得更好的性能。”你应该问他是否a)更聪明,b)比那些深入Oracle或SQL Server优化代码的典型人更受教育。可能性不大。
答案 11 :(得分:5)
让我们考虑一个示例:一张包含发票记录的表格,以及一张包含发票行项目记录的相关表格。考虑客户端伪代码:
for each (invoice in invoices)
let invoiceLines = FindLinesFor(invoice)
...
如果您有100,000张发票,每张发票10行,此代码将从100万个表中查找10个发票行,并且将执行100,000次。随着表格大小的增加,选择操作的数量会增加,会增加每个选择操作的成本。
如果您有几千条或更少的记录,那么计算机速度很快,您可能不会注意到两种方法之间的性能差异。由于成本增加超过线性,随着记录数量的增加(比如数百万),您将开始注意到差异,随着数据集大小的增加,差异将变得不那么容忍。
然而,加入。将使用表的索引并合并两个数据集。这意味着您有效地扫描第二个表一次而不是随机访问N次。如果定义了外键,则数据库已经存在内部存储的相关记录之间的链接。
想象一下自己这样做。您有一个按字母顺序排列的学生名单和一份包含所有学生成绩报告的笔记本(每个班级一页)。笔记本按学生的名字按顺序排序,顺序与列表相同。您希望如何继续?
或者:
答案 12 :(得分:5)
如果没有加入,您如何将订单商品与订单联系起来? 这是关系数据库管理系统的重点。 没有连接就没有关系数据,你也可以使用文本文件 处理数据。
听起来他不理解这个概念所以他试图让它看起来毫无用处。他认为excel是一个数据库应用程序的人是同一类型的人。 愚蠢地告诉他,让他阅读更多有关数据库的内容。通过C#建立多个连接并提取数据和合并数据是错误的做事方式。
答案 13 :(得分:3)
我怀疑他对应该使用哪些数据库的看法有限。最大化性能的一种方法是将整个数据库读入内存。在这种情况下,您可能会获得更好的性能,并且您可能希望在内存效率的情况下执行连接。然而,这并不是真正使用数据库,作为数据库恕我直言。
答案 14 :(得分:3)
我会说我遇到了一个案例,它更快地打破了查询并在代码中进行连接。话虽这么说,只有一个特定版本的MySQL,我必须这样做。其他一切,数据库可能会更快(请注意,您可能必须优化查询,但它仍然会更快)。
答案 15 :(得分:3)
他肯定是错的。虽然在C#或Java等语言中对数据操作有一定的优势,但由于SQL本身的性质,数据库中的连接速度最快。
SQL会详细记录有关数据的统计信息,如果您已正确创建索引,则可以非常快速地找到数百万条记录。除了你为什么要在数据库级别上正确地执行连接时,为什么要将所有数据拖入C#进行连接?
当您需要迭代地执行某些操作时,使用C#的优点就会发挥作用。如果您需要为每一行执行某些功能,则在C#中执行此操作可能会更快,否则,在数据库中优化连接数据。
答案 16 :(得分:2)
他错了,加入是有能力的程序员使用的。可能有一些有限的情况,他提出的方法更有效(并且我可能会使用Documant数据库),但如果你有任何数量的数据,我看不到它。例如,请使用此查询:
select t1.field1
from table1 t1
join table2 t2
on t1.id = t2.id
where t1.field2 = 'test'
假设table1中有1000万条记录,table2中有100万条记录。假设表1中的900万条记录符合where子句。假设它们中只有15个也在table2中。您可以运行此sql语句,如果正确编制索引,则该语句将花费毫秒数,并且仅使用1列数据在网络上返回15条记录。或者,您可以使用2列数据发送1000万条记录,并通过网络分别发送另外1百万条记录和一列数据,并将它们组合到Web服务器上。
当然,您可以随时将数据库的全部内容保留在Web服务器上,如果您的数据和数据不断变化,那么这只是非常愚蠢的。如果您不需要关系数据库的质量,那么不要使用它。但如果你这样做,那就正确使用它。
答案 17 :(得分:2)
在我作为软件开发人员的职业生涯中,我经常听到这种说法。几乎每次声明时,提出索赔的人对关系数据库系统,工作方式以及应该使用这些系统的方式都知之甚少。
是的,当使用错误时,连接似乎没用,甚至是危险的。但是,当以正确的方式使用时,数据库实现有很多潜在的优势来执行优化并“帮助”开发人员最有效地检索正确的结果。
不要忘记使用JOIN
告诉数据库您希望这些数据彼此相关的方式,从而为数据库提供有关 您的更多信息正在努力做到,因此能够更好地满足您的需求。
所以答案肯定是:不,JOINS
根本没用!
答案 18 :(得分:2)
不,不仅在ad-hoc C#/ Java的数据库代码中更好地优化了连接;但通常可以应用几种过滤技术,从而产生更好的性能。
答案 19 :(得分:0)
这在技术上是真实的仅在一种情况下在应用程序中不经常使用(当查询返回连接中的所有表的所有行时)。在大多数查询中,只返回每个表的一小部分行。数据库引擎通常使用索引来消除不需要的行,有时甚至不读取实际行,因为它可以使用存储在索引中的值。数据库引擎本身是用C,C ++等编写的,并且至少与开发人员编写的代码一样高效。
答案 20 :(得分:0)
除非我严重误解,否则问题中的逻辑是非常有缺陷的
如果每个A中B中有20行,则A中的1000行表示B中有20k行。 B中不能只有100行,除非有许多表“AB”,其中20k行包含映射。
因此,要获得有关100个B行中哪20个映射到每个A行的所有信息,您也可以使用AB表。所以这可能是:
因此,在检查数据时,客户端中的“JOIN”会添加任何值。并不是说这不是一个坏主意。如果我从数据库中检索一个对象,那么将它分解为单独的结果集会更有意义。对于报告类型调用,我几乎总是把它变成一个。
无论如何,我认为这种规模的交叉连接几乎没有用处。这是一个糟糕的例子。
你必须在某个地方加入,这就是RDBMS擅长的。我不想与任何认为可以做得更好的客户代码猴子合作。
有感:
要加入客户端需要持久对象,例如DataTables(在.net中)。如果你有一个扁平的结果集,它可以通过像DataReader这样更轻的东西来消费。高容量=用于避免数据库JOIN的大量客户端资源。