【问题标题】:Multiple Joins - Performance多个连接 - 性能
【发布时间】:2021-08-02 05:49:45
【问题描述】:

我有三张桌子:

表 A(大约 500 000 条记录)

ID ID_B Text
1 10 bla
2 10 blabla
3 30 blablabla

表 B(大约 100 000 条记录)

ID Text
10 blab
20 blaba
30 blabb

表 C(大约 600 000 条记录)

ID ID_A
1 1
2 1
3 2

现在我想加入这三个表:

SELECT A.Text
FROM A
     JOIN B ON B.ID = A.ID_B 
     JOIN C ON C.ID_A = A.ID

我在表 A 上创建了聚集主键索引 (ID) 和非聚集索引 (ID_B)。

根据执行计划,一开始使用聚集索引连接A和C。 之后,结果集按列 ID_B 排序,然后用于与 B 的合并连接。

Execution Plan

排序操作是最昂贵的。 (约占总成本的 40%)

有没有办法在整体性能方面优化这个查询?

【问题讨论】:

  • 当您只想要一张表中的一列时,为什么要JOIN
  • 使用“粘贴计划”向我们展示您的执行计划
  • @Larnu 可能是只有在存在 fk 关系的情况下才应该包含结果(也可以通过使用 exists 来完成)。鉴于信息有限,显然只是我的猜测。
  • @Larnu:因为我不需要 A 中的所有行
  • 请参阅paste the plan 了解在您的问题中包含执行计划的更好方法。请阅读this,了解一些改进问题的技巧。

标签: sql sql-server performance tsql join


【解决方案1】:

您没有提到表 B 上是否有任何索引。也许上面有一个带有标识符的索引并“包括”您要输出的任何列。

现在,根据我在 cmets 中收集的信息,您实际上主要是作为过滤器加入表 b 和 c,而不是因为您需要从这些表中输出数据。如果确实如此,您应该使用exists。您可能会回避子查询,但引擎知道如何处理exists。您会在计划中看到它将运行“半联接”。

select    a.text
from      a
where     exists (select 0 from b where b.id = a.id_b) 
and       exists (select 0 from c where c.id_a = a.id)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    相关资源
    最近更新 更多