2012-06-25 53 views
1

如何優化下面的SQL(我的複雜查詢的簡化視圖)。理想情況下,我應該能夠緩存第一個SQL結果(order ID)並在OrderLine表上進行某種投影第二個查詢。在SQL中緩存內部查詢

任何指針都會有幫助。

限制 - 我無法創建臨時表,光標或過程/函數。我連接到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) 
    ) 
) 

回答

2

優化器負責優化您的查詢;放鬆,讓它做它的東西。你可以通過使用CTE(公用表表達式,也就是WITH子句)來使公共查詢更明確一些,例如臨時表(你已經排除了)以命名公共子查詢。但是無論如何,優化器可能會以相同的方式處理事情。

您可以用JOIN替換IN子句;這可能會更快。無論如何,優化器可能會這樣做。但是,這不是一個緩存操作;這是一個標準的查詢重寫。

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; 
+0

得到它之前,我可以提交! –

+0

@karephul使用CTE的想法是,它可以找到結果集,然後在查詢中使用它們。它具有在SQL中允許無限遞歸和圖靈完整性的缺點。 –

+1

@DavidManheim它只允許遞歸達100級,這絕對不會加速查詢。 'CTE'根本不增加任何性能優勢。我大約有99%的積極性,這將會和原來的執行計劃一樣。 – JNK

0

選擇ORDER_ID,mod_id 從訂單Ø 內加入下列訂單醇 上o.order_id = ol.order_line_id

0

你可能會能夠刪除此行:

WHERE order_id IN (Select order_id FROM Orders) 

如果您的數據庫具有完整性,則沒有孤兒allo結婚和這條線不會過濾任何東西。

+1

如果優化器很聰明(Oracle是否足夠聰明?),它會通過在存在FK時刪除此檢查來優化查詢。 –

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; 
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) 
)