假设我有:
- 非常宽的表 A,我需要所有列
- 我需要加入一个有很多行的小表 B。
当然,当我连接这两个表时,我会返回 B 的每一行的 A 的所有内容。
这是内部被优化掉还是所有这些数据都是通过网络发送的?
因为如果这是最后一件事,在这种非常特殊的情况下,我只需很少的努力就可以在内存中手动连接。
例子:
SELECT ColumnA1, ColumnA2, ColumnA3, ColumnB1
FROM TableA
JOIN TableB ON TableB.Id = TableA.TableBId
得出数据:
ColumnA1 ColumnA2 ColumnA3 ColumnB1
------------------------------------------------
LargeTextA LargeTextB LargeTextC 1
LargeTextA LargeTextB LargeTextC 2
LargeTextA LargeTextB LargeTextC 3
LargeTextA LargeTextB LargeTextC [1.000.000 times more]
LargeTextA、LargeTextB 和 LargeTextC 是否会通过线路传输 1.000.000 次,还是只发送一次,因为它知道这只是重复的数据?
它将重复内容。SQLServer 不会尝试再次猜测为什么您需要所有这些数据,也不会尝试进行插值以减少发送的总体量。
如果您将表连接在一起并通过部分键(即,不是 1:1),那么您将在表 A 的每行中获得这种乘法效果(即,1:n)。
如果仅仅因为连接谓词是部分的而导致大量整个结果行重复,那么 DISTINCT 将有助于减少一点:例如, rowA1 rowB1 rowA1 rowB1 变成 rowA1 rowB1 但是两行中的所有字段都需要相同发生的情况。
我怀疑你确实有一个连接谓词给你 1: 并且你对此无能为力。
您可能会发现通过返回初始行集可以提高性能,该行集如下: rowApk rowBpk
然后重新查询 tableA/tableB 中的特定行,而不是尝试一次性消耗整个大行集。
如果出现分页问题,请查看客户端选项来游标数据(而不是尝试使用整个结果集),或者将结果放入另一个对象(tempdb 中的工作表、# 表等)中并从中批量检索那里。
最有可能的是,您应该了解如何改进表结构以帮助简化您需要返回的内容。