优化程序为其访问计划生成左深 (left-deep) 处理树。这一规则的唯一例外是存在右深 (right-deep) 嵌套外部连接表达式的情况。查询执行引擎的用于计算 LEFT OUTER JOIN 或 RIGHT OUTER JOIN 的算法要求,保留的表必须在任何连接策略中先于提供空值的表。因此,只要可能,优化程序就会寻找机会将 LEFT 或 RIGHT 外连接转换为内连接,这是因为内连接是可交换的,它使优化程序在执行连接枚举时具有更大的自由度。
如果以下条件之一为真,则 LEFT 或 RIGHT 外连接会转换为内连接:
当查询引用使用外连接编写的一个或多个视图时,此重写优化可应用于外连接查询。该查询的 WHERE 子句可以包括限制输出的条件,以便从一个或多个表的表达式中排除所有提供空值的行,从而使这种优化适用。
对于下面的查询,针对 SalesOrderItems 表的每一行,均恰好存在与 Products 表匹配的一行,因为 ProductID 列声明为非 NULL,并且 SalesOrderItems 表具有以下外键: "FK_ProductID_ID" ("ProductID") REFERENCING "Products" ("ID")
.
以下 SELECT 语句显示执行重写优化后如何重写查询:
SELECT * FROM SalesOrderItems s LEFT OUTER JOIN Products p ON (p.ID = s.ProductID); SELECT * FROM SalesOrderItems s JOIN Products p ON (p.ID = s.ProductID); |
以下查询列出产品及其数量较大的相应订单;LEFT OUTER JOIN 确保列出所有产品,即使产品没有订单:
SELECT * FROM Products p KEY LEFT OUTER JOIN SalesOrderItems s WHERE s.Quantity > 15; |
该查询的问题在于,由于谓语 s.Quantity > 15
将在 s.Quantity
为 NULL 的情况下被解释为 FALSE,因此 WHERE 子句中的谓语将从结果中排除所有没有订单的产品。该查询在语义上等效于:
SELECT * FROM Products p KEY JOIN SalesOrderItems s WHERE s.Quantity > 15; |
这种重写形式即为数据库服务器优化的查询。
在此示例中,该查询的编写几乎毫无疑问地存在错误;它应该改为:
SELECT * FROM Products p KEY LEFT OUTER JOIN SalesOrderItems s ON s.Quantity > 15; |
这样,数量的测试就是外连接条件的一部分。您可以将一些没有订单的新产品插入 Products 表中,然后再次执行这两个查询,这样就可以发现它们的区别。
INSERT INTO Products SELECT ID + 10, Name, Description, 'Extra large', Color, 50, UnitPrice, Photo FROM Products WHERE Name = 'Tee Shirt'; |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |