在SQL中缓存内部查询

时间:2012-06-25 15:55:08

标签: sql optimization query-optimization

如何优化以下SQL(复杂查询的简化视图)。理想情况下,我应该能够缓存第一个SQL结果(订单ID)并在第二个查询中对OrderLine表进行某种投影。

任何指针都会有所帮助。

限制 - 我无法创建临时表,游标或过程/函数。我正在连接到Oracle 10g。

SELECT 'Object_id', id, mod_id FROM
(
    (Select 'Order_id', order_id, mod_id FROM Orders)
    UNION
    (select 'Order_line_id', order_line_id, mod_id FROM OrderLine 
        WHERE order_id IN (Select order_id FROM Orders)
    )
) 

6 个答案:

答案 0 :(得分:2)

优化器负责优化您的查询;放松,让它做它的东西。

您尝试的任何显式缓存都会涉及临时表(您已排除)之类的内容,因此您可以通过使用CTE(公用表表达式,也就是WITH子句)来使公共查询更明确。命名公共子查询。但无论如何,优化器都可能以相同的方式处理事情。

您可以用JOIN替换IN子句;这可能会更快。同样,优化器可能会这样做。但是,这不是缓存操作;它是标准的查询重写。

答案 1 :(得分:1)

您可以根据以下示例设计查询:

WITH CTE AS
(
    Select 'Order_id' Descr, order_id, mod_id FROM Orders
)
, CTE2 AS
(
    SELECT * FROM CTE
    UNION
    SELECT 'Order_line_id' Descr, order_line_id, mod_id FROM OrderLine ol
    WHERE EXISTS (Select order_id FROM CTE WHERE order_id = ol.order_id)
)
SELECT * FROM CTE2;

答案 2 :(得分:0)

选择order_id,mod_id 来自订单o 内连接订单线ol 在o.order_id = ol.order_line_id

答案 3 :(得分:0)

您可以删除此行:

 WHERE order_id IN (Select order_id FROM Orders)

如果您的数据库具有完整性,则不允许孤立,此行不会过滤任何内容。

答案 4 :(得分:0)

with myOrders as (
  select order_id,
         mod_id
  from   Orders
)
select 'order_id' obj_type,
       order_id,
       mod_id
from   myOrders

union all

select 'order_line_id' obj_type,
       order_line_id,
       mod_id
from   OrderLine
join   myOrders
on     OrderLine.order_id = myOrders.order_id;

答案 5 :(得分:0)

您可以尝试以下内容......

SELECT DISTINCT 'Object_id', id, mod_id
FROM
(
    SELECT
        CASE
            WHEN CROSSNUM = 1 THEN 'Order_ID'
            ELSE 'Order_Line_ID'
        END AS Object_ID,
        CASE
            WHEN CROSSNUM = 1 THEN order_id
            ELSE order_line_id
        END AS id,
        CASE
            WHEN CROSSNUM = 1 THEN Orders.mod_id
            ELSE OrderLine.mod_id
        END AS mod_id
    FROM
        (Select 'Order_id', order_id, mod_id FROM Orders) Orders
    LEFT JOIN (select 'Order_line_id', order_line_id, mod_id FROM OrderLine) OrderLine
        ON Orders.Order_id = OrderLine.Order_Id
    CROSS JOIN
    (
        SELECT 1 AS CROSSNUM FROM DUAL
        UNION ALL
        SELECT 2 AS CROSSNUM FROM DUAL
    ) X
WHERE
    NOT (CROSSNUM = 2 AND order_line_id IS NULL)
)