PostgreSql的Explain命令詳解

来源:https://www.cnblogs.com/smiler/archive/2019/01/10/10250110.html
-Advertisement-
Play Games

http://toplchx.iteye.com/blog/2091860 使用EXPLAIN PostgreSQL為每個收到的查詢設計一個查詢規劃。選擇正確的匹配查詢結構和數據屬性的規劃對執行效率是至關重要要的,所以系統包含一個複雜的規劃器來試圖選擇好的規劃。你可以使用EXPLAIN命令查看查詢規 ...


http://toplchx.iteye.com/blog/2091860 使用EXPLAIN PostgreSQL為每個收到的查詢設計一個查詢規劃。選擇正確的匹配查詢結構和數據屬性的規劃對執行效率是至關重要要的,所以系統包含一個複雜的規劃器來試圖選擇好的規劃。你可以使用EXPLAIN命令查看查詢規劃器創建的任何查詢。閱讀查詢規劃是一門藝術,需要掌握一定的經驗,本節試圖涵蓋一些基礎知識。 以下的例子來自PostgreSQL 9.3開發版。 EXPLAIN基礎 查詢規劃是以規劃為節點的樹形結構。樹的最底節點是掃描節點:他返回表中的原數據行。 不同的表有不同的掃描節點類型:順序掃描,索引掃描和點陣圖索引掃描。 也有非表列源,如VALUES子句並設置FROM返回,他們有自己的掃描類型。 如果查詢需要關聯,聚合,排序或其他操作,會在掃描節點之上增加節點執行這些操作。通常有不只一種可能的方式做這些操作,所以可能出現不同的節點類型。 EXPLAIN的輸出是每個樹節點顯示一行,內容是基本節點類型和執行節點的消耗評估。可能會楚翔其他行,從彙總行節點縮進顯示節點的其他屬性。第一行(最上節點的彙總行)是評估執行計劃的總消耗,這個值越小越好。 下麵是一個簡單的例子: Sql代碼  收藏代碼
  1. EXPLAIN SELECT * FROM tenk1;  
  2.   
  3.                          QUERY PLAN  
  4. -------------------------------------------------------------  
  5.  Seq Scan on tenk1  (cost=0.00..458.00 rows=10000 width=244)  
因為這個查詢沒有WHERE子句,所以必須掃描表中的所有行,所以規劃器選擇使用簡單的順序掃描規劃。括弧中的數字從左到右依次是:
  • 評估開始消耗。這是可以開始輸出前的時間,比如排序節點的排序的時間。
  • 評估總消耗。假設查詢從執行到結束的時間。有時父節點可能停止這個過程,比如LIMIT子句。
  • 評估查詢節點的輸出行數,假設該節點執行結束。
  • 評估查詢節點的輸出行的平均位元組數。
這個消耗的計算依賴於規劃器的設置參數,這裡的例子都是在預設參數下運行。 需要知道的是:上級節點的消耗包括其子節點的消耗。這個消耗值只反映規劃器關心的內容,一般這個消耗不包括將數據傳輸到客戶端的時間。 評估的行數不是執行和掃描查詢節點的數量,而是節點返回的數量。它通常會少於掃描數量,因為有WHERE條件會過濾掉一些數據。理想情況頂級行數評估近似於實際返回的數量 回到剛纔的例子,表tenk1有10000條數據分佈在358個磁碟頁,評估時間是(磁碟頁*seq_page_cost)+(掃描行*cpu_tuple_cost)。預設seq_page_cost是1.0,cpu_tuple_cost是0.01,所以評估值是(358 * 1.0) + (10000 * 0.01) = 458   現在我們將查詢加上WHERE子句: Sql代碼  收藏代碼
  1. EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 7000;  
  2.   
  3.                          QUERY PLAN  
  4. ------------------------------------------------------------  
  5.  Seq Scan on tenk1  (cost=0.00..483.00 rows=7001 width=244)  
  6.    Filter: (unique1 < 7000)  
查詢節點增加了“filter”條件。這意味著查詢節點為掃描的每一行數據增加條件檢查,只輸入符合條件數據。評估的輸出記錄數因為where子句變少了,但是掃描的數據還是10000條,所以消耗沒有減少,反而增加了一點cup的計算時間。 這個查詢實際輸出的記錄數是7000,但是評估是個近似值,多次運行可能略有差別,這中情況可以通過ANALYZE命令改善。   現在再修改一下條件 Sql代碼  收藏代碼
  1. EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100;  
  2.   
  3.                                   QUERY PLAN  
  4. ------------------------------------------------------------------------------  
  5.  Bitmap Heap Scan on tenk1  (cost=5.07..229.20 rows=101 width=244)  
  6.    Recheck Cond: (unique1 < 100)  
  7.    ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0)  
  8.          Index Cond: (unique1 < 100)  
查詢規劃器決定使用兩步規劃:首先子查詢節點查看索引找到符合條件的記錄索引,然後外層查詢節點將這些記錄從表中提取出來。分別提取數據的成本要高於順序讀取,但因為不需要讀取所有磁碟頁,所以總消耗比較小。(其中Bitmap是系統排序的一種機制)   現在,增加另一個查詢條件: Sql代碼  收藏代碼
  1. EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND stringu1 = 'xxx';  
  2.   
  3.                                   QUERY PLAN  
  4. ------------------------------------------------------------------------------  
  5.  Bitmap Heap Scan on tenk1  (cost=5.04..229.43 rows=1 width=244)  
  6.    Recheck Cond: (unique1 < 100)  
  7.    Filter: (stringu1 = 'xxx'::name)  
  8.    ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0)  
  9.          Index Cond: (unique1 < 100)  
增加的條件stringu1='xxx'減少了輸出記錄數的評估,但沒有減少時間消耗,應為系統還是要查詢相同數量的記錄。請註意stringu1不是索引條件。  如果在不同的欄位上有獨立的索引,規劃器可能選擇使用AND或者OR組合索引: Sql代碼  收藏代碼
  1. EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000;  
  2.   
  3.                                      QUERY PLAN  
  4. -------------------------------------------------------------------------------------  
  5.  Bitmap Heap Scan on tenk1  (cost=25.08..60.21 rows=10 width=244)  
  6.    Recheck Cond: ((unique1 < 100) AND (unique2 > 9000))  
  7.    ->  BitmapAnd  (cost=25.08..25.08 rows=10 width=0)  
  8.          ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0)  
  9.                Index Cond: (unique1 < 100)  
  10.          ->  Bitmap Index Scan on tenk1_unique2  (cost=0.00..19.78 rows=999 width=0)  
  11.                Index Cond: (unique2 > 9000)  
 這個查詢條件的兩個欄位都有索引,索引不需要filre。   下麵我們來看看LIMIT的影響: Sql代碼  收藏代碼
  1. EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2;  
  2.   
  3.                                      QUERY PLAN  
  4. -------------------------------------------------------------------------------------  
  5.  Limit  (cost=0.29..14.48 rows=2 width=244)  
  6.    ->  Index Scan using tenk1_unique2 on tenk1  (cost=0.29..71.27 rows=10 width=244)  
  7.          Index Cond: (unique2 > 9000)  
  8.          Filter: (unique1 < 100)  
這條查詢的where條件和上面的一樣,只是增加了LIMIT,所以不是所有數據都需要返回,規劃器改變了規劃。在索引掃描節點總消耗和返回記錄數是運行玩查詢之後的數值,但Limit節點預期時間消耗是15,所以總時間消耗是15.增加LIMIT會使啟動時間小幅增加(0.25->0.29)。   來看一下通過索引欄位的表連接: Sql代碼  收藏代碼
  1. EXPLAIN SELECT *  
  2. FROM tenk1 t1, tenk2 t2  
  3. WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2;  
  4.   
  5.                                       QUERY PLAN  
  6. --------------------------------------------------------------------------------------  
  7.  Nested Loop  (cost=4.65..118.62 rows=10 width=488)  
  8.    ->  Bitmap Heap Scan on tenk1 t1  (cost=4.36..39.47 rows=10 width=244)  
  9.          Recheck Cond: (unique1 < 10)  
  10.          ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..4.36 rows=10 width=0)  
  11.                Index Cond: (unique1 < 10)  
  12.    ->  Index Scan using tenk2_unique2 on tenk2 t2  (cost=0.29..7.91 rows=1 width=244)  
  13.          Index Cond: (unique2 = t1.unique2)  
這個規劃中有一個內連接的節點,它有兩個子節點。節點摘要行的縮進反映了規劃樹的結構。最外層是一個連接節點,子節點是一個Bitmap掃描。外部節點點陣圖掃描的消耗和記錄數如同我們使用SELECT...WHERE unique1 < 10,因為這時t1.unique2 = t2.unique2還不相關。接下來為每一個從外部節點得到的記錄運行內部查詢節點。這裡外部節點得到的數據的t1.unique2值是可用的,所以我們得到的計劃和SELECT...WHEREt2.unique2=constant的情況類似。(考慮到緩存的因素評估的消耗可能要小一些) 外部節點的消耗加上迴圈內部節點的消耗(39.47+10*7.91)再加一點CPU時間就得到規劃的總消耗。   再看一個例子: Sql代碼  收藏代碼
  1. EXPLAIN SELECT *  
  2. FROM tenk1 t1, tenk2 t2  
  3. WHERE t1.unique1 < 10 AND t2.unique2 < 10 AND t1.hundred < t2.hundred;  
  4.   
  5.                                          QUERY PLAN  
  6. ---------------------------------------------------------------------------------------------  
  7.  Nested Loop  (cost=4.65..49.46 rows=33 width=488)  
  8.    Join Filter: (t1.hundred < t2.hundred)  
  9.    ->  Bitmap Heap Scan on tenk1 t1  (cost=4.36..39.47 rows=10 width=244)  
  10.          Recheck Cond: (unique1 < 10)  
  11.          ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..4.36 rows=10 width=0)  
  12.                Index Cond: (unique1 < 10)  
  13.    ->  Materialize  (cost=0.29..8.51 rows=10 width=244)  
  14.          ->  Index Scan using tenk2_unique2 on tenk2 t2  (cost=0.29..8.46 rows=10 width=244)  
  15.                Index Cond: (unique2 < 10)  
條件t1.hundred<t2.hundred不在tenk2_unique2索引中,所以這個條件出現在連接節點中。這將減少連接節點的評估輸出記錄數,但不會改變子節點的掃描數。 註意這次規劃器選擇使用Meaterialize節點,將條件加入內部節點,這以為著內部節點的索引掃描只做一次,即使嵌套迴圈需要讀取這些數據10次,Meterialize節點將數據保存在記憶體中,每次迴圈都從記憶體中讀取數據。   如果我們稍微改變一下查詢,會看到完全不同的規劃: Sql代碼  收藏代碼
  1. EXPLAIN SELECT *  
  2. FROM tenk1 t1, tenk2 t2  
  3. WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;  
  4.   
  5.                                         QUERY PLAN  
  6. ------------------------------------------------------------------------------------------  
  7.  Hash Join  (cost=230.47..713.98 rows=101 width=488)  
  8.    Hash Cond: (t2.unique2 = t1.unique2)  
  9.    ->  Seq Scan on tenk2 t2  (cost=0.00..445.00 rows=10000 width=244)  
  10.    ->  Hash  (cost=229.20..229.20 rows=101 width=244)  
  11.          ->  Bitmap Heap Scan on tenk1 t1  (cost=5.07..229.20 rows=101 width=244)  
  12.                Recheck Cond: (unique1 < 100)  
  13.                ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0)  
  14.                      Index Cond: (unique1 < 100)  
這裡規劃器選擇使用hash join,將一個表的數據存入記憶體中的哈希表,然後掃描另一個表並和哈希表中的每一條數據進行匹配。 註意縮進反應的規劃結構。在tenk1表上的bitmap掃描結果作為Hash節點的輸入建立哈希表。然後Hash Join節點讀取外層子節點的數據,再迴圈檢索哈希表的數據。   另一個可能的連接類型是merge join:   Sql代碼  收藏代碼
  1. EXPLAIN SELECT *  
  2. FROM tenk1 t1, onek t2  
  3. WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;  
  4.   
  5.                                         QUERY PLAN  
  6. ------------------------------------------------------------------------------------------  
  7.  Merge Join  (cost=198.11..268.19 rows=10 width=488)  
  8.    Merge Cond: (t1.unique2 = t2.unique2)  
  9.    ->  Index Scan using tenk1_unique2 on tenk1 t1  (cost=0.29..656.28 rows=101 width=244)  
  10.          Filter: (unique1 < 100)  
  11.    ->  Sort  (cost=197.83..200.33 rows=1000 width=244)  
  12.          Sort Key: t2.unique2  
  13.          ->  Seq Scan on onek t2  (cost=0.00..148.00 rows=1000 width=244)  
Merge Join需要已經排序的輸入數據。在這個規劃中按正確順序索引掃描tenk1的數據,但是對onek表執行排序和順序掃描,因為需要在這個表中查詢多條數據。因為索引掃描需要訪問不連續的磁碟,所以索引掃描多條數據時會頻繁使用排序順序掃描(Sequential-scan-and-sort)。 有一種方法可以看到不同的規劃,就是強制規劃器忽略任何策略。例如,如果我們不相信排序順序掃描(sequential-scan-and-sort)是最好的辦法,我們可以嘗試這樣的做法: Sql代碼  收藏代碼
  1. SET enable_sort = off;  
  2.   
  3. EXPLAIN SELECT *  
  4. FROM tenk1 t1, onek t2  
  5. WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2;  
  6.   
  7.                                         QUERY PLAN  
  8. ------------------------------------------------------------------------------------------  
  9.  Merge Join  (cost=0.56..292.65 rows=10 width=488)  
  10.    Merge Cond: (t1.unique2 = t2.unique2)  
  11.    ->  Index Scan using tenk1_unique2 on tenk1 t1  (cost=0.29..656.28 rows=101 width=244)  
  12.          Filter: (unique1 < 100)  
  13.    ->  Index Scan using onek_unique2 on onek t2  (cost=0.28..224.79 rows=1000 width=244)  
顯示測結果表明,規劃器認為索引掃描比排序順序掃描消耗高12%。當然下一個問題就是規劃器的評估為什麼是正確的。我們可以通過EXPLAIN ANALYZE進行考察。   EXPLAIN ANALYZE 通過EXPLAIN ANALYZE可以檢查規劃器評估的準確性。使用ANALYZE選項,EXPLAIN實際運行查詢,顯示真實的返回記錄數和運行每個規劃節點的時間,例如我們可以得到下麵的結果: Sql代碼  收藏代碼
  1. EXPLAIN ANALYZE SELECT *  
  2. FROM tenk1 t1, tenk2 t2  
  3. WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2;  
  4.   
  5.                                                            QUERY PLAN  
  6. ---------------------------------------------------------------------------------------------------------------------------------  
  7.  Nested Loop  (cost=4.65..118.62 rows=10 width=488) (actual time=0.128..0.377 rows=10 loops=1)  
  8.    ->  Bitmap Heap Scan on tenk1 t1  (cost=4.36..39.47 rows=10 width=244) (actual time=0.057..0.121 rows=10 loops=1)  
  9.          Recheck Cond: (unique1 < 10)  
  10.          ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..4.36 rows=10 width=0) (actual time=0.024..0.024 rows=10 loops=1)  
  11.                Index Cond: (unique1 < 10)  
  12.    ->  Index Scan using tenk2_unique2 on tenk2 t2  (cost=0.29..7.91 rows=1 width=244) (actual time=0.021..0.022 rows=1 loops=10)  
  13.          Index Cond: (unique2 = t1.unique2)  
  14.  Total runtime: 0.501 ms  
註意,實際時間(actual time)的值是已毫秒為單位的實際時間,cost是評估的消耗,是個虛擬單位時間,所以他們看起來不匹配。 通常最重要的是看評估的記錄數是否和實際得到的記錄數接近。在這個例子里評估數完全和實際一樣,但這種情況很少出現。   某些查詢規劃可能執行多次子規劃。比如之前提過的內迴圈規劃(nested-loop),內部索引掃描的次數是外部數據的數量。在這種情況下,報告顯示迴圈執行的總次數、平均實際執行時間和數據條數。這樣做是為了和評估值表示方式一至。由迴圈次數和平均值相乘得到總消耗時間。   某些情況EXPLAIN ANALYZE會顯示額外的信息,比如sort和hash節點的時候: Sql代碼  收藏代碼
  1. EXPLAIN ANALYZE SELECT *  
  2. FROM tenk1 t1, tenk2 t2  
  3. WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous;  
  4.   
  5.                                                                  QUERY PLAN  
  6. --------------------------------------------------------------------------------------------------------------------------------------------  
  7.  Sort  (cost=717.34..717.59 rows=101 width=488) (actual time=7.761..7.774 rows=100 loops=1)  
  8.    Sort Key: t1.fivethous  
  9.    Sort Method: quicksort  Memory: 77kB  
  10.    ->  Hash Join  (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)  
  11.          Hash Cond: (t2.unique2 = t1.unique2)  
  12.          ->  Seq Scan on tenk2 t2  (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)  
  13.          ->  Hash  (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)  
  14.                Buckets: 1024  Batches: 1  Memory Usage: 28kB  
  15.                ->  Bitmap Heap Scan on tenk1 t1  (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)  
  16.                      Recheck Cond: (unique1 < 100)  
  17.                      ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0) (actual time=0.049..0.049 rows=100 loops=1)  
  18.                            Index Cond: (unique1 < 100)  
  19.  Total runtime: 8.008 ms  
排序節點(Sort)顯示排序類型(一般是在記憶體還是在磁碟)和使用多少記憶體。哈希節點(Hash)顯示哈希桶和批數以及使用記憶體的峰值。   另一種額外信息是過濾條件過濾掉的記錄數: Sql代碼  收藏代碼
  1. EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE ten < 7;  
  2.   
  3.                                                QUERY PLAN  
  4. ---------------------------------------------------------------------------------------------------------  
  5.  Seq Scan on tenk1  (cost=0.00..483.00 rows=7000 width=244) (actual time=0.016..5.107 rows=7000 loops=1)  
  6.    Filter: (ten < 7)  
  7.    Rows Removed by Filter: 3000  
  8.  Total runtime: 5.905 ms  
這個值在join節點上尤其有價值。"Rows Removed"只有在過濾條件過濾掉數據時才顯示。   類似條件過濾的情況也會在"lossy"索引掃描時發生,比如這樣一個查詢,一個多邊形含有的特定的點: Sql代碼  收藏代碼
  1. EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)';  
  2.   
  3.                                               QUERY PLAN  
  4. ------------------------------------------------------------------------------------------------------  
  5.  Seq Scan on polygon_tbl  (cost=0.00..1.05 rows=1 width=32) (actual time=0.044..0.044 rows=0 loops=1)  
  6.    Filter: (f1 @> '((0.5,2))'::polygon)  
  7.    Rows Removed by Filter: 4  
  8.  Total runtime: 0.083 ms  
規劃器認為(正確的)這樣的表太小以至於不需要索引掃描,所以採用順序掃描所有行經行條件檢查。 但是,如果我們強制使用索引掃描,將會看到: Sql代碼  收藏代碼
  1. SET enable_seqscan TO off;  
  2.   
  3. EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)';  
  4.   
  5.                                                         QUERY PLAN  
  6. --------------------------------------------------------------------------------------------------------------------------  
  7.  Index Scan using gpolygonind on polygon_tbl  (cost=0.13..8.15 rows=1 width=32) (actual time=0.062..0.062 rows=0 loops=1)  
  8.    Index Cond: (f1 @> '((0.5,2))'::polygon)  
  9.    Rows Removed by Index Recheck: 1  
  10.  Total runtime: 0.144 ms  
這裡我們可以看到索引返回一條候選數據,但被過濾條件拒絕。這是因為GiST索引在多邊形包含檢測上是鬆散的"lossy":它實際返回哪些和多邊形交疊的數據,然後我們還需要針對這些數據做包含檢測。   EXPLAIN還有BUFFERS選項可以和ANALYZE一起使用,來得到更多的運行時間分析: Sql代碼  收藏代碼
  1. EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000;  
  2.   
  3.                                                            QUERY PLAN  
  4. ---------------------------------------------------------------------------------------------------------------------------------  
  5.  Bitmap Heap Scan on tenk1  (cost=25.08..60.21 rows=10 width=244) (actual time=0.323..0.342 rows=10 loops=1)  
  6.    Recheck Cond: ((unique1 < 100) AND (unique2 > 9000))  
  7.    Buffers: shared hit=15  
  8.    ->  BitmapAnd  (cost=25.08..25.08 rows=10 width=0) (actual time=0.309..0.309 rows=0 loops=1)  
  9.          Buffers: shared hit=7  
  10.          ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0) (actual time=0.043..0.043 rows=100 loops=1)  
  11.                Index Cond: (unique1 < 100)  
  12.                Buffers: shared hit=2  
  13.          ->  Bitmap Index Scan on tenk1_unique2  (cost=0.00..19.78 rows=999 width=0) (actual time=0.227..0.227 rows=999 loops=1)  
  14.                Index Cond: (unique2 > 9000)  
  15.                Buffers: shared hit=5  
  16.  Total runtime: 0.423 ms   
Buffers提供的數據可以幫助確定哪些查詢是I/O密集型的。   請註意EXPLAIN ANALYZE實際運行查詢,任何實際影響都會發生。如果要分析一個修改數據的查詢又不想改變你的表,你可以使用roll back命令進行回滾,比如: Sql代碼  收藏代碼
  1. BEGIN;  
  2.   
  3. EXPLAIN ANALYZE UPDATE tenk1 SET hundred = hundred + 1 WHERE unique1 < 100;  
  4.   
  5.                                                            QUERY PLAN  
  6. --------------------------------------------------------------------------------------------------------------------------------  
  7.  Update on tenk1  (cost=5.07..229.46 rows=101 width=250) (actual time=14.628..14.628 rows=0 loops=1)  
  8.    ->  Bitmap Heap Scan on tenk1  (cost=5.07..229.46 rows=101 width=250) (actual time=0.101..0.439 rows=100 loops=1)  
  9.          Recheck Cond: (unique1 < 100)  
  10.          ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=101 width=0) (actual time=0.043..0.043 rows=100 loops=1)  
  11.                Index Cond: (unique1 < 100)  
  12.  Total runtime: 14.727 ms  
  13.   
  14. ROLLBACK;  
當查詢是INSERT,UPDATE或DELETE命令時,在頂級節點是實施對錶的變更。在這下麵的節點實行定位舊數據計算新數據的工作。所以我們看到一樣的bitmap索引掃描,並返回給Update節點。值得註意的是雖然修改數據的節點可能需要相當長的運行時間(在這裡它消耗了大部分的時間),規劃器卻沒有再評估時間中添加任何消耗,這是因為更新工作對於任何查詢規劃都是一樣的,所以並不影響規劃器的決策。   EXPLAIN ANALYZE的"Total runtime"包括執行啟動和關閉時間,以及運行被激發的任何處觸發器的時間,但不包括分析、重寫或規劃時間。執行時間包括BEFORE觸發器,但不包括AFTER觸發器,因為AFTER是在查詢運行結束之後才觸發的。每個觸發器(無論BEFORE還是AFTER)的時間也會單獨顯示出來。註意,延遲的觸發器在事務結束前都不會被執行,所以EXPLAIN ANALYZE不會顯示。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ORA-04021: timeout occurred while waiting to lock object 某個應用正在鎖定該表或者包表為select b.SID,b.SERIAL#,c.SQL_TEXTfrom v$locked_object a, v$session b, v$sqlare ...
  • 有時候,我們需要給redis庫中插入大量的數據,如做性能測試前的準備數據。遇到這種情況時,偶爾可能也會懵逼一下,這裡就給大家介紹一個批量導入數據的方法。 先準備一個redis protocol的文件(redis protocol可以參考這裡:https://redis.io/topics/proto ...
  • 當我們希望MySQL能夠以更高的性能運行查詢時,最好的辦法就是弄清楚MySQL是如何優化和執行查詢的。一旦理解了這一點,很多查詢優化工作實際上就是遵循一些原則讓優化器能夠按照預想的合理方式運行 ...
  • 正文 通常創建Oracle資料庫都是通過 DBCA (Database Configuration Assistant)工具完成的, DBCA 工具可以通過兩種方式完成建庫任務,即圖形界面方式和靜默命令行方式。既然安裝資料庫軟體可以通過靜默方式來完成,創建資料庫也可以通過靜默方式來完成,本文就對使用 ...
  • Elastic是目前全文搜索引擎的首選,本質上是一個非關係型資料庫,許多知名公司都是使用它來做全文搜索,比如github,本文介紹了一些它的基本的操作,後面還會學習一些更高級的知識,比如中文分詞,與項目結合使用等等 ...
  • 輸入命令: :~$ pip install mysqlclient 報錯: Collecting mysqlclient Using cached https://files.pythonhosted.org/packages/f7/a2/1230ebbb4b91f42ad6b646e59eb885 ...
  • 一張表有兩個相同的商品排序信息,不同的是 type值和sort不同,如果有type等於1那就連接type等於一的那條商品信息進行排序,如果沒有等於0的那就連排序等於0的進行排序 ...
  • 狂神聲明 : 文章均為自己的學習筆記 , 轉載一定註明出處 ; 編輯不易 , 防君子不防小人~共勉 ! mysql學習【第2篇】:MySQL數據管理 外鍵管理 外鍵概念 如果公共關鍵字在一個關係中是主關鍵字,那麼這個公共關鍵字被稱為另一個關係的外鍵。由此可見,外鍵表示了兩個關係之間的相關聯繫。以另一 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...