Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 查询处理 » 查询优化与执行 » 语义查询转换

 

排除不必要的内连接和外连接

连接排除重写优化会通过从查询中排除表(如果这样做足够安全)来降低查询的连接度。通常,此优化应用于定义为主键到外键连接或主键到主键连接的内连接。连接排除优化也可以应用于外连接中使用的表(虽然使这种优化有效的条件要复杂得多)。

此优化不排除可使用 UPDATE 或 DELETE WHERE CURRENT 更新的表(即使这样做是正确的)。这会对查询的性能造成负面影响。然而,如果查询为只读,则可以在 SELECT 语句中指定 FOR READ ONLY,以确保执行连接排除。注意,尽管主查询块中的表是可更新的,但在子查询或嵌套派生表中出现的表是固有不可更新的。

简而言之,该重写优化适用于以下三种主要连接:

  • 连接属于主键到外键连接,且在查询中只引用主表中的主键列。在这种情况下,如果主键表是不可更新的,则它会被排除。

  • 连接属于同一表的两个实例之间的主键到主键连接。在这种情况下,如果其中一个表是不可更新的,则它会被排除。

  • 连接属于外连接,且提供空值的表表达式具有以下属性:

    • 对于外连接的保留一侧的每一行,提供空值的表表达式最多返回一行。

    • 在外连接以外的其余查询中,不需要任何由提供空值的表表达式所生成的表达式。

示例

例如,在下面的查询中,连接属于主键到外键的连接,主键表、Products 表可以被排除:

SELECT s.ID, s.LineID, p.ID
FROM SalesOrderItems s KEY JOIN Products p
FOR READ ONLY;

该查询将被重写为:

SELECT s.ID, s.LineID, s.ProductID
FROM SalesOrderItems s
WHERE s.ProductID IS NOT NULL
FOR READ ONLY;

由于 SalesOrderItems 表中具有引用 Products 表的 NULL 外键的任何行都不会出现在结果中,因此第二个查询在语义上与第一个查询等效。

在以下查询中,如果提供空值的表表达式不能为保留一侧的任何行生成多个行,且在 LEFT OUTER JOIN 上没有使用 Products 表中的任何列,则 OUTER JOIN 可以被排除。

SELECT s.ID, s.LineID
FROM SalesOrderItems s LEFT OUTER JOIN Products p ON p.ID = s.ProductID
WHERE s.Quantity > 5 
FOR READ ONLY;

该查询将被重写为:

SELECT s.ID, s.LineID
FROM SalesOrderItems s  
WHERE s.Quantity > 5 
FOR READ ONLY;