2013-03-25 75 views
0

注:我目前運行在一個sqlite3的DB我的問題查詢,雖然從專業知識解答任何其他DBMS會歡迎各界有識之士...SQL優化器/執行計劃 - 重複子查詢

我想知道如果查詢優化器試圖識別重複的查詢/子查詢並且只運行一次,如果是的話。

這裏是我的示例查詢:

SELECT * 
    FROM table1 AS t1 
WHERE t1.fk_id = 
(
    SELECT t2.fk_id 
     FROM table2 AS t2 
    WHERE t2.id = 1111 
) 
OR t1.fk_id = 
(
    SELECT local_id 
     FROM ID_MAP 
    WHERE remote_id = 
    (
     SELECT t2.fk_id 
      FROM table2 AS t2 
     WHERE t2.id = 1111 
    ) 
); 

將嵌套查詢

SELECT t2.fk_id 
    FROM table2 AS t2 
WHERE t2.id = 1111 

只運行一次(和它的結果緩存進一步的訪問)?

它不是什麼大不了的事在這個例子中,因爲它的一個簡單的查詢只執行了兩次,但是我需要爲每個孩子記錄運行 約4-5次(2次,兩次,所以真的8-10 )在我的實際程序中(它抓取所有與父記錄(表2)關聯的子記錄(table1) ,由一個外鍵綁定,它還檢查一個id映射表,以確保它查詢 爲本地生成的id,以及真實/更新/新密鑰)。

我真的很感謝任何幫助,謝謝。

回答

1

SQLite的具有非常簡單的查詢優化,並且甚至沒有嘗試檢測相同的子查詢:

> create table t(x); 
> explain query plan 
    select * from t 
    where x in (select x from t) or 
     x in (select x from t); 
0|0|0|SCAN TABLE t (~500000 rows) 
0|0|0|EXECUTE LIST SUBQUERY 1 
1|0|0|SCAN TABLE t (~1000000 rows) 
0|0|0|EXECUTE LIST SUBQUERY 2 
2|0|0|SCAN TABLE t (~1000000 rows) 

的SQLite沒有名爲表表達式(WITH) ;如果性能真的很重要,那麼最好的辦法是爲子查詢的結果創建一個臨時表。

+0

」解釋查詢計劃「我甚至不知道DBMS有這樣的命令,這非常好。我遇到的問題的核心是將本地生成的臨時ID與遠程數據庫更新後發回的「真實」同步。它變得棘手的父/子外鍵關係b/c。父級和子級記錄都可以在本地生成,因此獲取臨時ID,並使用ID_MAP表進行跟蹤。我試圖避免應用程序級鎖,但我不確定最好的辦法是使用事務(開始/提交)還是嵌套查詢來打敗潛在的競爭條件? – samosaris 2013-03-25 17:17:24

+0

爲了防止比賽,請使用交易。 (沒有顯式事務,每個命令都會被包裝成一個自動事務,所以圍繞多個命令的顯式事務甚至可以減少事務開銷。)但是,應用程序級鎖可能比[SQLite的鎖定方案]更高效(http: //www.sqlite.org/faq.html#q5)。無論如何,在實際出現性能問題之前不要打擾優化。 – 2013-03-25 18:11:35

+0

好的。嵌套查詢是自動觸發的,還是會被分解爲單獨的語句(反過來將它們封裝到單個事務中)?我問b/c我不知道如果天氣或不是你暗示嵌套查詢不被原子地解僱(因此阻止比賽)?感謝所有的幫助。 – samosaris 2013-03-25 19:39:31

1

至於你問其他的DB洞察....

在Oracle數據庫管理系統,任何獨立的子查詢將只執行一次。

SELECT t2.fk_id 
    FROM table2 AS t2 
WHERE t2.id = 1111 -- The result will be the same for any row in t1. 

當然,依賴子查詢需要重複執行。從屬子查詢的

實施例:

SELECT t2.fk_id 
    FROM table2 AS t2 
WHERE t2.id = t1.t2_id -- t1.t2_id will have different values for different rows in t1. 
+0

有趣的概念,在/依賴子查詢。總的來說,在寫這個問題的時候,我沒有明白。謝謝! 「 – samosaris 2013-03-25 15:41:01