我有多个SQL查询,我一个接一个地运行以获取一组数据。在每个查询中,有一些连接的表与其他查询完全相同。例如:
查询1
SELECT * FROM
Product1TableA A1
INNER JOIN Product1TableB B on A1.BId = B.Id
INNER JOIN CommonTable1 C on C.Id = B.CId
INNER JOIN CommonTable2 D on D.Id = B.DId
...
查询2
SELECT * FROM Product2TableA A2
INNER JOIN Product2TableB B on A2.BId = B.Id
INNER JOIN CommonTable1 C on C.Id = B.CId
INNER JOIN CommonTable2 D on D.Id = B.DId
...
我正在玩重新排序连接(每个查询加入大约2个表),我在这里读到它们不应该真正影响查询执行,除非SQL"放弃"在优化期间,因为查询有多大......
我想知道的是,如果在我的所有查询开始时聚合常见的表连接实际上有帮助......
答案 0 :(得分:2)
理论上,join
子句中from
s的顺序对查询性能没有影响。对于少数表,应该没有区别。优化器应找到最佳执行路径。
对于大量表格,优化程序可能必须将有关join
顺序的搜索短路。然后它将使用启发式 - 这些可能会受到join
订单的影响。
早期的查询对特定的执行计划没有影响。
如果您遇到性能问题,我猜测join
顺序不是根本原因。我在SQL Server中遇到的最常见的问题是不适当的嵌套循环连接 - 这些可以使用优化器提示进行处理。
答案 1 :(得分:1)
Gordon的回答是一个很好的解释,但this answer解释了JOIN的行为,并指出SQL Server的版本是相关的:
虽然在优化中更改了连接顺序,但是优化器 不会尝试所有可能的连接订单。当它找到它时会停止 认为可行的解决方案是优化使用的行为 宝贵的资源。
虽然优化器会尽力为JOIN选择一个好的订单,但是有很多JOIN会产生更大的机会来获得一个不那么好的计划。
就个人而言,我在ERP中的一些视图中看到过很多JOIN,他们通常都运行正常。但是,有时候(基于客户端的数据量,实例配置等),这些视图中的一些选择比预期的要多得多。
如果此数据到达实际应用程序(.NET,JAVA等),则一种方法是缓存来自所有小表的信息,将其存储为字典(散列)并基于密钥执行O(1)查找。
这提供了减少JOIN计数和不对这些表执行数据库读取的优点(缓存数据时除外)。但是,这会增加应用程序的复杂性(缓存管理)。
另一个解决方案是使用临时表并在多个查询中填充它们,以避免每个查询中有多个JOIN。这个解决方案通常表现更好,并且还增加了可调试性(如果查询没有提供正确的数据或根本没有数据,那么10-15个JOIN中的哪个是问题?)。
所以,我对你的问题的回答是:你可能会从重新排序JOIN条款中获得一些好处,但我建议首先避免使用大量的JOIN。
答案 2 :(得分:1)
我想我明白了他想说/要做的事情:
我想知道的是,如果在开始时聚集公共表连接 我的所有查询实际上都有帮助...
想象一下,您有一些查询,每个查询都有超过3个内部联接。查询是不同的,但总是(例如)3个共同的表连接在相同的字段上。现在的问题是: 如果每个查询都将以连接中的这3个表开始,并且所有其他表在之后加入,将会发生什么?
答案是它不会改变任何东西,即优化器会按照它认为最佳执行的方式重新排列表格。
例如,如果将这3个连接的结果保存到临时表中,然后使用此保存的结果与其他表连接,则可能会发生变化。但这取决于您的查询使用的过滤器。如果你有适当的索引,并且你的查询过滤器足够有选择性(这样你的查询返回很少的行),就不需要缓存具有太多行的中间无过滤结果,因为优化器可以选择先过滤每个表,然后才加入他们