循环、哈希和合并联接。如果指定了多个联接提示,则优化器从允许的联接策略中选择开销最少的联接策略。此外,也可以使用OPTION子句指定联接策略。但是这种方式会影响查询中的所有联接,通常用于旧式联接语法。
1.为每个联接指定单独的联接策略
可以在FROM子句中使用LOOP JOIN、MERGE JOIN和HASH JOIN提示符为每个联接单独指定联接策略。例如,下面的查询语句指定使用嵌套循环联接。
USE AdventureWorks;
GO
SELECT *
FROM Sales.Customer
INNER LOOPJOIN Sales.SalesOrderHeader
ONCustomer.CustomerID = SalesOrderHeader.CustomerID;
又如,下面的查询语句指定使用合并联接。
USE AdventureWorks;
GO
SELECT *
FROM Sales.Customer
INNERMERGE JOIN Sales.SalesOrderHeader
ONCustomer.CustomerID = SalesOrderHeader.CustomerID;
在多表联接中使用联接提示时,会影响联接的执行顺序。在前面介绍了,在不影响返回结果正确的情况下,查询优化器会按照效率优先的原则,选择首先执行的联接。例如,下面语句的执行计划如图7-16所示,可以看到首先执行的是Sales.SalesOrderHeader与Sales.SalesOrderDetail的联接,然后将联接结果再与Sales.Customer进行联接。
USE AdventureWorks;
GO
SELECT *
FROM Sales.Customer
INNER JOINSales.SalesOrderHeader
ONCustomer.CustomerID = SalesOrderHeader.CustomerID
INNER JOINSales.SalesOrderDetail
ONSalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID;

图7-16未使用联接提示的执行计划
下面的语句为Sales.Customer和Sales.SalesOrderHeader指定了合并联接提示,并且这个提示仅对这两个表起作用,与Sales.SalesOrderDetail的联接策略仍旧由查询优化器决定。由于明确指定了Sales.Customer与Sales.SalesOrderHeader使用合并联接,优化器会先执行该联接,而不是先执行Sales.SalesOrderHeader与Sales.SalesOrderDetail的联接。否则,就会造成Sales.Customer与Sales.SalesOrderHeader和Sales.SalesOrderDetail的联接结果再执行合并联接。图7-17是该语句的执行计划。
SELECT *
FROM Sales.Customer
INNERMERGE JOIN Sales.SalesOrderHeader
ONCustomer.CustomerID = SalesOrderHeader.CustomerID
INNER JOINSales.SalesOrderDetail
ONSalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID;

图7-17使用联接提示后的执行计划
如果希望Sales.Customer与Sales.SalesOrderHeader和Sales.SalesOrderDetail的联接结果执行合并联接,则应当使用嵌套联接的方式实现,参考下面的语句:
SELECT *
FROM Sales.Customer
INNERMERGE JOIN (Sales.SalesOrderHeader
INNER JOIN Sales.SalesOrderDetail
ONSalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID)
ONCustomer.CustomerID = SalesOrderHeader.CustomerID;
2.为全部联接指定统一的联接策略
当使用旧式联接语法时,应当使用OPTION子句指定联接策略,但是,这种策略会影响语句中的全部联接,无法为每个联接单独指定不同的联接策略,如:
SELECT *
FROM Sales.Customer, Sales.SalesOrderHeader,Sales.SalesOrderDetail
WHERE Customer.CustomerID =SalesOrderHeader.CustomerID
ANDSalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
OPTION (MERGE JOIN);
该语句的执行计划如图7-18所示,可以看到三个表之间全部使用了合并联接策略。

图7-18为全部联接使用统一联接策略的执行计划
在ANSI SQL:1992规范中,也可以使用OPTION子句,它同样也是影响语句中的全部联接,如:
SELECT *
FROM Sales.Customer
INNER JOINSales.SalesOrderHeader
ONCustomer.CustomerID = SalesOrderHeader.CustomerID
INNER JOINSales.SalesOrderDetail
ONSalesOrderHeader.SalesOrderID = SalesOrderDetail.SalesOrderID
OPTION (MERGE JOIN);