回答

收藏

一个大联接或多个查询哪个提供更好的性能?

技术问答 技术问答 168 人阅读 | 0 人回复 | 2023-09-14

我有一张叫订单的桌子。订单上的一列是customer_id,
0 U- _- d6 N; i% z) v我有一个名为“ customers”的表,具有10个字段
( K' C8 h) x& T5 m5 _6 k8 L给定两个选项,如果我要建立一个订单对象数组并将其嵌入到一个客户对象中,那么我有两个选择。$ `# j' n3 F( c4 q" |
选项1:1 r" D, [* k$ Q9 b+ I
一种。首先查询订单表。b。遍历记录并查询人员表以获取人员的记录7 e) R' _0 o  c! a7 S
这将是这样的:" Y" K4 `, j2 Q4 Q3 j  y$ h% V
Select * from APplications
) ~8 S: I$ W7 \ Select * from Customer where id = 1
4 w" M& K. E) I1 e1 D+ w Select * from Customer where id = 26 X. t3 w) F( k3 }' b
Select * from Customer where id = 3  j  o$ B% w) B- E4 K- L
Select * from Customer where id = etc . . .$ a! i9 k5 I# ^" t5 }% ?
选项2:6 d; V+ R/ C/ @. D' V! ]( P# @) _
一种。在所有领域参加% g# k; P9 |8 }1 W
#2是显而易见的,因为您只执行一个查询,而不是1 + [numberOforders]个查询(可能是数百个或更多)  V8 Z4 c! n. t/ b/ L
就像这样:% H, w) y2 \3 r
Select * from Applications a, Customers c) k% i" U8 h" H' @( I3 V
Innerjoin c.id = a.customerID, D9 Z# |& a: I/ {) v; T
我的主要问题是,如果我还有10个其他订单表之外的其他表(类似于客户),而您在订单表中有ID,该怎么办?您应该执行一个将这10个表联接起来的查询,还是在某种程度上这样做效率低下:  }. W3 k0 G! N: t0 W3 A( A9 K: x4 _
任何建议都将有所帮助..是否有任何优化来确保快速性能
3 k9 J$ P4 o; h8 C% ^: h                4 n- Z$ a0 t6 m. X8 s
解决方案:5 U1 b# a8 y7 t+ p9 _/ e+ ?/ y% v& C
                . e9 j  R, H7 ~$ u
3 T- q; ?  O$ e; H& `/ W

$ Y, {% S3 O2 Z( @                我同意每个人的观点,即即使有很多表,单联接也可能会更有效率。与在应用程序代码中完成工作相比,这也减少了开发工作量。假定表已正确索引,每个外键列上都有一个索引,并且(当然)每个主键列上都有一个索引。' I6 b  A: a# o. M, V5 M8 _
最好的选择是首先尝试最简单的方法(大连接),然后查看其效果如何。如果运行良好,那就太好了-您已完成。如果执行不佳,请分析查询并查找表中缺少的索引。
! \& N: d3 r+ c由于网络往返次数(如anijhaw所述),您的选择#1不太可能执行良好。有时这称为“选择N + 1”问题-
6 C  L- Y0 |0 |* \: }* ~您执行一个SELECT以获得N个应用程序的列表,然后循环执行N
  S- r5 O& S3 f, {& H, e" ?$ HSELECTs以获取客户。对于应用程序程序员来说,这种一次记录循环是很自然的。但是当您一次处理整个数据集时,SQL的效果要好得多。
4 X4 `+ _( ]9 D' i' C: P3 A如果即使索引良好,选项#2还是很慢,则您可能需要研究缓存。您可以在数据库中(使用摘要表或物化/索引视图),在应用程序中(如果有足够的RAM)或专用的缓存服务器(例如memcached)中进行缓存。当然,这取决于查询结果的最新程度。如果所有内容都必须是最新的,则每当底层表更新时,任何高速缓存都必须进行更新-
( |1 i* U+ g0 A2 z7 ]. G' X它变得复杂并且变得不太有用。$ `: s! l2 I+ R
但是,这听起来像是报告查询,并且报告通常不需要实时。因此缓存可能可以为您提供帮助。5 u: K- ^" ~, ?4 T, n
根据您的DBMS,要考虑的另一件事是此查询对命中同一数据库的其他查询的影响。如果您的DBMS允许读取器阻止编写器,则此查询可能需要很长时间才能运行,因此可能阻止对表的更新。那将是不好的。Oracle没有此问题,在“读取已提交的快照”模式下运行时,SQL
/ Z' ^: |) O' b2 d4 o) gServer也没有。我不了解MySQL。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则