一個順序磁盤頁面操作的cost值由系統參數seq_page_cost (floating point)參數指定的,由於這個參數默認為1.0,所以我們可以認為一次順序磁盤頁面操作的cost值為1。
下面
osdba=# explain select * from t;
QUERY PLAN
———————————————————-
Seq Scan on t (cost=0.00 ..4621.00 rows=300000 width=10 )
(1 row)
cost=說明:
- 第一個數字0.00表示啟動cost,這是執行到返回第一行時需要的cost值。
- 第二個數字4621.00表示執行整個SQL的cost
可以explain后加analyze來通過真實執行這個SQL來獲得真實的執行計划和執行時間:.
osdba=# EXPLAIN ANALYZE SELECT * FROM t;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
Seq Scan on t (cost=0.00..4621.00 rows=300000 width=10) (actual time=0.022 ..355.380rows=300000 loops=1)
Total runtime: 696.074 ms
actual time=中的第一個數字表示返回第一行需要的時間(叫啟動時間),第二個數字表示執行這個整個花的時間。后面的rows=300000是實際的行數。
表順序掃描由於是立即可以獲得第一行,所以啟動時間一般都是0,而如果是排序操作,則需要處理完所有行后才能返回第一行,所以排序操作是需要啟動時間的,下表列出了哪些操作是需要啟動時間的,哪些操作不是需要的:
執行計划運算類型 | 操作說明 | 是否有啟動時間 |
---|---|---|
Seq Scan | 掃描表 | 無啟動時間 |
Index Scan | 索引掃描 | 無啟動時間 |
Bitmap Index Scan | 索引掃描 | 有啟動時間 |
Bitmap Heap Scan | 索引掃描 | 有啟動時間 |
Subquery Scan | 子查詢 | 無啟動時間 |
Tid Scan | ctid = …條件 | 無啟動時間 |
Function Scan | 函數掃描 | 無啟動時間 |
Nested Loop | 循環結合 | 無啟動時間 |
Merge Join | 合並結合 | 有啟動時間 |
Hash Join | 哈希結合 | 有啟動時間 |
Sort | 排序,ORDER BY操作 | 有啟動時間 |
Hash | 哈希運算 | 有啟動時間 |
Result | 函數掃描,和具體的表無關 | 無啟動時間 |
Unique | DISTINCT,UNION操作 | 有啟動時間 |
Limit | LIMIT,OFFSET操作 | 有啟動時間 |
Aggregate | count, sum,avg, stddev集約函數 | 有啟動時間 |
Group | GROUP BY分組操作 | 有啟動時間 |
Append | UNION操作 | 無啟動時間 |
Materialize | 子查詢 | 有啟動時間 |
SetOp | INTERCECT,EXCEPT | 有啟動時 |
explain select distinct course_id from course where course_term = 'Fal02';
NOTICE: QUERY PLAN:
Unique (cost=12223.09..12339.76 rows=4667 width=4)
-> Sort (cost=12223.09..12223.09 rows=46666 width=4)
-> Seq Scan on course (cost=0.00..8279.99 rows=46666 width=4)
1.從下往上讀
2.explain報告查詢的操作,開啟的消耗,查詢總的消耗,訪問的行數 訪問的平均寬度
3.開啟時間消耗是輸出開始前的時間例如排序的時間
4.消耗包括磁盤檢索頁,cpu時間
5.注意,每一步的cost包括上一步的
6.重要的是,explain 不是真正的執行一次查詢 只是得到查詢執行的計划和估計的花費
索引有用條件 當滿足特定條件的元組數小於總的數目
1. cost
含義:這個計划節點的預計的啟動開銷和總開銷
詳細描述:啟動開銷是指一個計划節點在返回結果之前花費的開銷,如果是在一個排序節點里,那就是指執行排序花費的開銷。 總開銷是指一個計划節點從開始到運行完成,即所有可用行被檢索完后,總共花費的開銷。實際上,一個節點的父節點可能會在子節點返回一部分結果后,停止繼續讀取剩余的行,如Limit節點。
2. rows
含義:這個計划節點的預計輸出行數
詳細描述:在帶有ANALYZE選項時,SQL語句會實際運行,這時一個計划節點的代價輸出會包含兩部分,前面部分是預計的代價,后面部分是實際的代價。前面部分中rows是指預計輸出行數,后面部分是指實際輸出行數。如果中間節點返回的數據量過大,最終返回的數據量很小,或許可以考慮將中間節點以下的查詢修改成物化視圖的形式。
3. width
含義:這個計划節點返回行的預計平均寬度(以字節計算)
詳細描述:如果一個掃描節點返回行的平均寬度明顯小於子節點返回行的平均寬度,說明從子節點讀取的大部分數據是無用的,或許應該考慮一下調整SQL語句或表的相關設計,比如讓執行計划盡量選擇Index Only Scan,或者對表進行垂直拆分。
4. actual time
含義:這個計划節點的實際啟動時間和總運行時間
詳細描述:啟動時間是指一個計划節點在返回第一行記錄之前花費的時間。 總運行時間是指一個計划節點從開始到運行完成,即所有可用行被檢索完后,總共花費的時間。
5. loops
含義:這個計划節點的實際重啟次數
詳細描述:如果一個計划節點在運行過程中,它的相關參數值(如綁定變量)發生了變化,就需要重新運行這個計划節點。
6. Filter
含義:這個掃描節點的過濾條件
詳細描述:對於一個表的掃描節點,如果相關的條件表達式不能對應到表上的某個索引,可能需要分析一下具體的原因和影響,比如該表相關的字段在表達式中需要進行隱式類型轉換,那么即使在該字段上存在索引,也不可能被使用到。如:((b.intcol)::numeric > 99.0)
7. Index Cond
含義:這個索引掃描節點的索引匹配條件
詳細描述:說明用到了表上的某個索引。
8. Rows Removed by Filter
含義:這個掃描節點通過過濾條件過濾掉的行數
詳細描述:如果一個掃描節點的實際輸出行數明顯小於通過過濾條件過濾掉的行數,說明這個計划節點在運行過程中的大量計算是無用的,或者說是沒有實際產出的,那么這個SQL語句或者表的相關設計可能不是特別好。