2013-07-15 77 views
3

我讀過連接比子查詢更好。如何理解SQLite`EXPLAIN QUERY PLAN`結果?

EXPLAIN QUERY PLAN 
SELECT Queue.Id, NULL 
    FROM Queue 
    INNER JOIN LastQueue 
    ON Queue.Id=LastQueue.Id 

Array 
(
    [0] => Array 
     (
      [selectid] => 0 
      [order] => 0 
      [from] => 0 
      [detail] => SCAN TABLE Queue (~1000000 rows) 
     ) 

    [1] => Array 
     (
      [selectid] => 0 
      [order] => 1 
      [from] => 1 
      [detail] => SEARCH TABLE LastQueue USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
     ) 

) 

EXPLAIN QUERY PLAN 
SELECT Queue.Id, NULL 
    FROM Queue 
    WHERE (SELECT 1 FROM LastQueue WHERE Queue.Id=LastQueue.Id) IS NOT NULL 

Array 
(
    [0] => Array 
     (
      [selectid] => 0 
      [order] => 0 
      [from] => 0 
      [detail] => SCAN TABLE Queue (~500000 rows) 
     ) 

    [1] => Array 
     (
      [selectid] => 0 
      [order] => 0 
      [from] => 0 
      [detail] => EXECUTE CORRELATED SCALAR SUBQUERY 1 
     ) 

    [2] => Array 
     (
      [selectid] => 1 
      [order] => 0 
      [from] => 0 
      [detail] => SEARCH TABLE LastQueue USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) 
     ) 

) 

我想我必須乘以行數來獲得成本的概念。我是對的?

然後,

  • 使用連接:1000000 * 1
  • 使用子查詢1:50萬* 1 * 1

然後,就是子查詢比join快?

有沒有一個很好的教程,學習如何理解EXPLAIN/EXPLAIN QUERY PLAN結果?

爲什麼說SCAN TABLE隊列是〜1000000和〜500000,當那個表有76行時?

+1

這裏是一個鏈接(** HTTPS://www.sqlite.org /eqp.html**)爲官方文檔**解釋查詢計劃**。它解釋了使用解釋查詢計劃所需要知道的一切 –

回答

6

EXECUTE CORRELATED SCALAR SUBQUERY 1就在那裏,因爲你使用的是不同的查詢語法。

實際執行情況在兩種情況下都是相同的:SQLite遍歷Queue表的所有記錄,並嘗試查找LastQueue表中的相應記錄。

估計記錄計數是不同的是不關心你的,因爲你知道的記錄實際數量是相同的。

聯接可能比其他數據庫中的子查詢更好,但在僅使用嵌套循環聯接的SQLite中,唯一的區別是聯接允許SQLite選擇聯接中的外部和內部表。

在任何情況下,您都應該以最簡單和可維護的方式編寫查詢,並且只有在測量得到明顯和必要的改進後才能對其進行優化。


請注意,而不是:

WHERE (SELECT ...) IS NOT NULL 

這將是更地道寫:

WHERE EXISTS (SELECT ...) 
1

解釋是給你的表不準確的計數。嘗試使用分析來收集表格上的統計信息,然後再次嘗試解釋。

我想你會發現兩個查詢將以幾乎相同的速度返回。也許子查詢由於一個額外的步驟而變慢。這裏要注意的重要一點是「SCAN TABLE」,它意味着它查看磁盤上的所有行。

http://www.sqlite.org/lang_analyze.html

而且是有可能有你的桌子上沒有索引?因爲它應該使用它們,但它似乎不是。確保在create table語句中使用主鍵。

http://www.sqlite.org/lang_createtable.html

+0

經過分析,連接是76 * 1,子查詢是38 * 1 * 1行。是的,我有一個主鍵('CREATE TABLE'Queue'('Id'INTEGER PRIMARY KEY NOT NULL)')。但我正確的乘以行數,還是應該採取其他操作來計算成本? – Oriol

+0

你爲什麼認爲SQLite可以使用另一個索引?對於一個連接,它*必須*查看所有'Queue'記錄。 –

+0

@CL。不是另一個索引,只有一個索引(即PK),並且是LastQueue表,因爲它是內部聯接。 – beiller