背景
在當今的軟件開發領域,盡管主流開發模式往往傾向于采用單表模式,力圖盡可能地減少表之間的連接操作,以期達到提高數據處理效率、簡化應用邏輯等目的。然而,對于那些已經上線運行多年的運維老系統而言,它們內部往往遺留了大量的復雜 SQL 語句。這些 SQL 語句在系統初建時,可能是基于當時的業務需求和數據量規模設計與實現。但隨著時間的推移,數據庫中的數據量持續不斷地累積和膨脹,原先執行起來速度較快的 SQL 語句,在面對如今海量的數據時,往往會出現性能大幅下降的情況,甚至可能成為整個系統的性能瓶頸,嚴重影響業務的正常運轉。
因此,在這樣的背景下,對這些關鍵 SQL 語句優化變得重要,而優化的前提則是對SQL進行分析,其重要手段就是查看SQL語句的執行計劃。
本文以Oracle數據庫為例,介紹下如何通過執行計劃來分析和解決問題。
一、什么是執行計劃?
執行計劃是 Oracle 數據庫用于執行 SQL 語句的一系列步驟。它描述了數據庫如何訪問和處理數據,包括表的掃描方式、連接順序、使用的索引等。
需要注意的是,數據庫根據內部的優化器成本模型來生成最優的執行計劃,以期以最快速度、最少資源完成 SQL 語句的執行。因此,并不是添加了索引,實際執行的時候一定會使用索引,數據庫會進行判斷和處理。
二、如何查看執行計劃?
查看執行計劃有以下幾種方式:
V$SQL_PLAN 視圖
首先,通過系統視圖V$SQL
獲取到SQL_ID,
SELECT * FROM V$SQL order by last_load_time desc
如下圖所示:
然后,通過V$SQL_PLAN
動態性能視圖,查看對應的 SQL 語句的執行計劃。
SELECT * FROM V$SQL_PLAN WHERE SQL_ID = '62v30b9v1fvcc';
結果如下圖所示:
這種方式依托于oracle數據庫提供的視圖,操作起來比較繁瑣,且結果也不夠直觀,不推薦。
explain plan 語句
語法
EXPLAIN PLAN FOR
是最基本的查看執行計劃的語法。它將生成的執行計劃存儲在數據字典表中。
分為兩步,第一步我們需要生成執行計劃,可以使用以下語句創建:
EXPLAIN PLAN SET STATEMENT_ID = 'stmt1' FOR select * from WEB_LINK where name='Property Sheet Pages';
這條語句會為查詢 WEB_LINK 表中 name 為 Property Sheet Pages 的記錄生成執行計劃,并且將這條計劃標記為 ‘stmt1’。
第二步是查看執行計劃,通過查詢 PLAN_TABLE
表來查看具體的執行計劃。
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE', 'stmt1', 'ALL'));
這里 DBMS_XPLAN.DISPLAY
函數用于格式化和顯示存儲在 PLAN_TABLE
中的執行計劃,參數 ‘PLAN_TABLE’ 指明存儲計劃的表,‘stmt1’ 是之前指定的標記,‘ALL’ 表示顯示所有信息,包括基本節點信息、成本、分區信息等。
執行結果如下:
Plan hash value: 506061415--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 165 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| WEB_LINK | 1 | 165 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | WEB_LINK_N | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------1 - SEL$1 / WEB_LINK@SEL$12 - SEL$1 / WEB_LINK@SEL$1Predicate Information (identified by operation id):
---------------------------------------------------2 - access("NAME"='Property Sheet Pages')Column Projection Information (identified by operation id):
-----------------------------------------------------------1 - "WEB_LINK"."IDENTITY"[VARCHAR2,20], "WEB_LINK"."DESCRIPTION"[VARCHAR2,255], "WEB_LINK"."GROUP_ID"[VARCHAR2,30], "WEB_LINK"."MODIFIABLE"[VARCHAR2,1], "WEB_LINK"."MODIFIED_ON"[DATE,7], "WEB_LINK"."MODIFIED_BY"[VARCHAR2,30], "WEB_LINK"."REMOVEFLAG"[VARCHAR2,1], "NAME"[VARCHAR2,100], "WEB_LINK"."URL"[VARCHAR2,255], "WEB_LINK"."SEPARATE_WINDOW"[VARCHAR2,1]2 - "WEB_LINK".ROWID[ROWID,10], "NAME"[VARCHAR2,100]
這種方式相比第一種,無論是便捷性,還是直觀性都要好上不少。
自動執行計劃
在 SQL*Plus 中,可以通過設置 AUTOTRACE
打開自動追溯功能后,來自動顯示執行計劃,包括操作步驟、行數預估、字節預估和成本等信息。
在 SQL Developer 中,執行 SQL 語句后,可以在 “執行計劃” 選項卡中查看圖形化或詳細文本形式的執行計劃,非常直觀方便。
該方式的便捷性和直觀性最佳,推薦采用該方式來查看執行計劃。