當前位置:首頁 » 編程語言 » sql執行計劃屬性
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sql執行計劃屬性

發布時間: 2023-06-14 15:07:38

1. 什麼是sql執行計劃

SQL執行計劃指的是查看一條SQL語句在資料庫中實際執行的時候,一步步的分別都做了什麼,具體資料庫查看執行計劃的操作步驟如下:

1、首先,打開一個的sql server的資料庫管理界面當中。

2. sql server執行計劃 怎麼看消耗資源

掃描:逐行遍歷數據。
先建立一張表,並給大家看看大概是什麼樣子的。

CREATE TABLE Person(
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(50) NULL,
Age int NULL,
Height int NULL,
Area nvarchar(50) NULL,
MarryHistory nvarchar(10) NULL,
EcationalBackground nvarchar(10) NULL,
Address nvarchar(50) NULL,
InSiteId int NULL
) ON [PRIMARY]

表中的數據14萬左右,大概類似下面這樣:

此表,暫時沒有任何索引。
一、數據訪問操作
1、表掃描
表掃描:發生於堆表,並且沒有可用的索引可用時,會發生表掃描,表示整個表掃描一次。
現在,我們來對此表執行一條簡單的查詢語句:
SELECT * From Person WHERE Name = '公子'

查看執行計劃如下:

表掃描,顧名思義就是整張表掃描,找到你所需要的數據了。
2、聚集索引掃描
聚集索引掃描:發生於聚集表,也相當於全表掃描操作,但在針對聚集列的條件如(WHERE Id > 10)等操作時,效率會較好。
下面我們在Id列來對此表加上一個聚集索引
CREATE CLUSTERED INDEX IX_Id ON Person(Id)

再次執行同樣的查詢語句:
SELECT * From Person WHERE Name = '公子'

執行計劃如下:

為什麼建的聚集索引在Id列,會對掃描有影響呢?更何況與Name條件也沒關系啊?
其實,你加了聚集索引之後,表就由堆表變成了聚集表。我們知道聚集表的數據存在於聚集索引的葉級節點。因此,聚集掃描與表掃描其實差別不大,要說差別大,也得看where條件里是什麼,以後返回的數據。就本條SQL語句而言,效率差別並不大。
可以看看I/O統計信息:
表掃描:

聚集索引掃描:

此處超出本文范疇了,效率不在本文考慮范圍內,本文只考慮的是,各種掃描的區別,以及為何會產生。
3、聚集索引查找
聚集索引查找:掃描聚集索引中特定范圍的行。
看執行以下SQL語句:
SELECT * FROM Person WHERE Id = '73164'

執行計劃如下:

4、索引掃描
索引掃描:整體掃描非聚集索引。
下面我們來添加一個聚集索引,並執行一條查詢語句:
CREATE NONCLUSTERED INDEX IX_Name ON Person(Name) --創建非聚集索引

SELECT Name FROM Person

查看執行計劃如下:

為什麼此處會選擇索引掃描(非聚集索引)呢?
因為此非聚集索引能夠覆蓋所需要的數據。如果非聚集索引不能覆蓋呢?例如,我們將SELECT改為SELECT *再來看看。

好明顯,返回結果所包括的記錄太多,用非聚集索引反而不合算。因此使用了聚集索引。
如果此時我們刪除聚集索引,再執行SELECT *看看。
DROP INDEX Person.IX_Id


而此時沒有聚集索引,所以只有使用表掃描。
5、書簽查找
前面關於索引的學習我們已經知道,當在非聚集索引中並非覆蓋和包含所需全部的列時,SQL Server會選擇,直接進行聚集索引掃描獲得數據,還是先去非聚集索引找到聚集索引鍵,然後利用聚集索引找到數據。
下面來看一個書簽查找的示例:
SELECT * FROM Person WHERE Name = '胖胖'--Name列有非聚集索引

執行計劃如下:

上面的過程可以理解為:首先通過非聚集索引找到所求的行,但這個索引並不包含所有的列,因此還要額外去基本表中找到這些列,因此要進行鍵查找,如果基本表是以堆進行組織的,那麼這個鍵查找(Key Lookup)就會變成RID查找(RID Lookup),鍵查找和RID查找統稱為書簽查找。不過有時當非聚集索引返回的行數過多時,SQL Server可能會選擇直接進行聚集索引掃描了。
二、流聚合操作
1、流聚合
流聚合:在相應排序的流中,計算多組行的匯總值。
所有的聚合函數(如COUNT(),MAX())都會有流聚合的出現,但是其不會消耗IO,只有消耗CPU。
例如執行以下語句:
SELECT MAX(Age) FROM Person

查看執行計劃如下:

2、計算標量
計算標量:根據行中的現有值計算新值。比如COUNT()函數,多一行,行數就加1咯。
除MIN和MAX函數之外的聚合函數都要求流聚合操作後面跟一個計算標量。
SELECT COUNT(*) FROM Person

查看執行計劃如下:

3、散列聚合(哈希匹配)
對於加了Group by的子句,因為需要數據按照group by 後面的列有序,就需要Sort來保證排序。注意,Sort操作是佔用內存的操作,當內存不足時還會去佔用tempdb。SQL Server總是會在Sort操作和散列匹配中選擇成本最低的。
SELECT Height,COUNT(Id) FROM Person --查出各身高的認輸
GROUP BY Height

執行計劃如下:

對於數據量比較大時,SQL Server選擇的是哈希匹配。
在內存中建立好散列表後,會按照group by後面的值作為鍵,然後依次處理集合中的每條數據,當鍵在散列表中不存在時,向散列表添加條目,當鍵已經在散列表中存在時,按照規則(規則是聚合函數,比如Sum,avg什麼的)計算散列表中的值(Value)。
4、排序
當數據量比價少時,例如執行以下語句,新建一個只有數十條記錄的與Person一樣的表。
SELECT * INTO Person2 FROM Person2
WHERE Id < 100

再來執行同樣的查詢語句:
SELECT Height,COUNT(Id) FROM Person2 --只是表換成了數據量比較少的表
GROUP BY Height

執行計劃如下:

三、連接
當多表連接時(包括書簽查找,索引之間的連接),SQL Server會採用三類不同的連接方式:循環嵌套連接,合並連接,散列連接。這幾種連接格式有適合自己的場景,不存在哪個更好的說法。
新建兩張表如下

這是一個簡單的新聞,欄目結構。
1、嵌套循環
先來看一個簡單的Inner Join查詢語句
SELECT * FROM Nx_Column AS C
INNER JOIN Nx_Article AS A
ON A.ColumnId = C.ColumnId

執行計劃如下:

循環嵌套連接的圖標同樣十分形象,處在上面的外部輸入(Outer input),這里也就是聚集索引掃描。和處在下面的內部輸入(Inner Input),這里也就是聚集索引查找。外部輸入僅僅執行一次,根據外部輸入滿足Join條件的每一行,對內部輸入進行查找。這里由於是7行,對於內部輸入執行7次。

根據嵌套循環的原理不難看出,由於外部輸入是掃描,內部輸入是查找,當兩個Join的表外部輸入結果集比較小,而內部輸入所查找的表非常大時,查詢優化器更傾向於選擇循環嵌套方式。
2、合並連接
不同於循環嵌套的是,合並連接是從每個表僅僅執行一次訪問。從這個原理來看,合並連接要比循環嵌套要快了不少。
從合並連接的原理不難想像,首先合並連接需要雙方有序.並且要求Join的條件為等於號。因為兩個輸入條件已經有序,所以從每一個輸入集合中取一行進行比較,相等的返回,不相等的舍棄,從這里也不難看出Merge join為什麼只允許Join後面是等於號。從圖11的圖標中我們可以看出這個原理。
SELECT * FROM Nx_Column AS C
INNER JOIN Nx_Article AS A
ON A.ColumnId = C.ColumnId
OPTION(MERGE join)

執行計劃如下:

如果輸入數據的雙方無序,則查詢分析器不會選擇合並連接,我們也可以通過索引提示強制使用合並連接,為了達到這一目的,執行計劃必須加上一個排序步驟來實現有序。這也是上述SQL語句為什麼要加OPTION(MERGE join)的原因。上述對Article表的ColumnId列進行了排序。
3、哈希連接
散列連接同樣僅僅只需要只訪問1次雙方的數據。散列連接通過在內存中建立散列表實現。這比較消耗內存,如果內存不足還會佔用tempdb。但並不像合並連接那樣需要雙方有序。
要進行下面這兩個實現,得把兩個列的聚集索引不要建在ColumnId列,否則不會採用哈希連接。
ALTER TABLE PK_Nx_Column DROP CONSTRAINT PK_Nx_Column --刪除主鍵
DROP INDEX Nx_Column.PK_Nx_Column --刪除聚集索引
CREATE CLUSTERED INDEX IX_ColumnName ON Nx_Column(ColumnName) --創建聚集索引
--這里再設置回主鍵就可以了,有了聚集索引,就不能隨主鍵默認建啦

還要刪除另外一個表Article的聚集索引哦。
然後執行以下查詢:
SELECT * FROM Nx_Column AS C
INNER JOIN Nx_Article AS A
ON A.ColumnId = C.ColumnId

執行計劃如下:

要刪除掉聚集索引,否則兩個有序輸入SQL Server會選擇代價更低的合並連接。SQL Server利用兩個上面的輸入生成哈希表,下面的輸入來探測,可以在屬性窗口看到這些信息,如圖15所示。

3. Mysql學會查看sql的執行計劃

首先在Mysql的服務中有 連接器、查詢緩存(Mysql8 已經刪除)、分析器、優化器、執行器等,所有跨存儲引擎的功能都在這一層實現

而一條sql怎麼執行是由優化器決定的, 優化器是在表裡面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的連接順序。

而執行計劃就是優化器優化後的sql的執行的詳細方案

Mysql中查看執行計劃的方式有兩種 : 1. 使用desc    2.使用 explain  使用它倆的效果是一樣的

接下來要通過執行計劃知道sql是怎麼執行的

執行計劃中有幾個重要的欄位, 分別是 

id,  table,  type,  possible_keys,  key,  key_len, Extra

id :  可以通過ID來查看在多表聯查中sql是先查詢哪張表的 id相同的從上往下依次執行,id不同的id大的先執行

table :   table當然就是查詢的表名

type :  查詢的類型   查詢類型分為  ALL,  index,  range,  ref , eq_ref, const(system),  null

        ALL: 指的全盤掃描,沒有走任何索引   查詢結果集大於25% 優化器可能會走全盤掃描   字元串查詢的時候一定要加"" 不然可能會全索引掃描(隱式轉換)   統計信息 失效 或者 過舊 也可能走全盤掃描  因為優化器會參考統計信息來制定執行計劃

        index: 全索引掃描  就是掃描整顆索引樹

           range: 索引范圍  查詢索引樹的一部分范圍   范圍索引中 >  <  <=  >=  like  的效率會比  or   in  的效率高, 使用like %再前面的不走索引

            ref:   輔助索引的等值查詢            

                    當查詢的數據量小,優化器也有可能會走索引的全盤掃描  這里我就不貼圖了;

            eq_ref : 多表連接查詢中,被連接的表的連接條件列是主鍵或者唯一鍵

            const(system): 主鍵 或者 唯一鍵 的等值查詢

               null: 沒有數據

            他們的性能是依次遞增的 全盤掃描性能最差,  const性能最高

possible_keys:  查詢過程中可能用到的索引

key: 真正使用到的索引

key_len:  走索引的長度

        這個是怎麼計算的呢?  

                key_len 的計算方法 :

                    int 類型最長存儲4個位元組長度的數字  有not null  是4位元組  沒有的話會花1位元組存儲是不是null

                    tinyint 最大存儲一個位元組    也會花1位元組來判斷是不是null

                    字元串類型 : 字元集 utf8mb4  1-4位元組

                    varchar超過255會預留2個位元組存儲長度 沒超預留1個位元組

                    key_len 永遠是你設置的長度的最大的  

        聯合索引可以通過key_len 來判斷走了幾個索引

        使用desc format=json select * from table 可以查看詳細情況

filtered:  索引掃描過濾掉數據的佔比

Extra: 額外的信息 

         Using filesort :MySQL 對數據在sql層進行了排序,而不是按照表內的索引進行排序讀 取。 效率比較低

         Using temporary :使用臨時表保存中間結果,也就是說 MySQL 在對查詢結果排序時使用了臨時表,常見於order by 或 group by。

         Using index :表示 SQL 操作中使用了覆蓋索引(Covering Index),避免了訪問表的數據行,效率高。

         Using index condition :表示 SQL 操作命中了索引,但不是所有的列數據都在索引樹上,還需要訪問實際的行記錄。

         Using where :表示 SQL 操作使用了 where 過濾條件。

         Select tables optimized away :基於索引優化 MIN/MAX 操作或者 MyISAM 存儲引擎優化 COUNT(*) 操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即可完成優化。

          Using join buffer (Block Nested Loop) :表示 SQL 操作使用了關聯查詢或者子查詢,且需要進行嵌套循環計算

 

4. 怎樣分析sql語句的執行計劃

寫好一段SQL代碼以後,可以通過查看SQL的執行計劃,初步預測該SQL在運行時的性能好壞,尤其是在sql調優時,我們可以通過查看執行計劃, 來分析sql性能問題,本文簡單介紹怎麼在plsql中查看SQL語句的執行計劃。
http://jingyan..com/article/ab69b270bffc2e2ca7189fee.html

5. 獲取SQL執行計劃的常見幾種方法

1. 預估執行計劃 - Explain Plan
Explain plan以SQL語句作為輸入,得到這條SQL語句的執行計劃,並將執行計劃輸出存儲到計劃表中。
首先,在你要執行的SQL語句前加explain plan for,此時將生成的執行計劃存儲到計劃表中,語句如下:
explain plan for SQL語句
然後,在計劃表中查詢剛剛生成的執行計劃,語句如下:
select * from table(dbms_xplan.display);
注意:Explain plan只生成執行計劃,並不會真正執行SQL語句,因此產生的執行計劃有可能不準,因為:
1)當前的環境可能和執行計劃生成時的環境不同;
2)不會考慮綁定變數的數據類型;
3)不進行變數窺視。
2. 查詢內存中緩存的執行計劃 (dbms_xplan.display_cursor)
如果你想獲取正在執行的或剛執行結束的SQL語句真實的執行計劃(即獲取library cache中的執行計劃),可以到動態性能視圖里查詢。方法如下:
1)獲取SQL語句的游標
游標分為父游標和子游標,父游標由sql_id(或聯合address和hash_value)欄位表示,子游標由child_number欄位表示。
如果SQL語句正在運行,可以從v$session中獲得它的游標信息,如:
select status, sql_id, sql_child_number from v$session where status='ACTIVE' and ....
如果知道SQL語句包含某些關鍵字,可以從v$sql視圖中獲得它的游標信息,如:
select sql_id, child_number, sql_text from v$sql where sql_text like '%關鍵字%『
2)獲取庫緩存中的執行計劃
為了獲取緩存庫中的執行計劃,可以直接查詢動態性能視圖v$sql_plan和v$sql_plan_statistics_all等,但更方便的方法是以sql_id和子游標為參數,執行如下語句:
select * from table(dbms_xplan.display_cursor('sql_id',child_number));
3)獲取前一次的執行計劃:
set serveroutput off
select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
3. 查詢歷史執行計劃(dbms_xplan.display_awr)
AWR會定時把動態性能視圖中的執行計劃保存到dba_hist_sql_plan視圖中,如果你想要查看歷史執行計劃,可以採用如下方法查詢:
select * from table(dbms_xplan.display_awr('sql_id');
4. 在用sqlplus做SQL開發是(Autotrace)
set autotrace是sqlplus工具的一個功能,只能在通過sqlplus連接的session中使用,它非常適合在開發時測試SQL語句的性能,有以下幾種參數可供選擇:
SET AUTOTRACE OFF ---------------- 不顯示執行計劃和統計信息,這是預設模式
SET AUTOTRACE ON EXPLAIN ------ 只顯示優化器執行計劃
SET AUTOTRACE ON STATISTICS -- 只顯示統計信息
SET AUTOTRACE ON ----------------- 執行計劃和統計信息同時顯示
SET AUTOTRACE TRACEONLY ------ 不真正執行,只顯示預期的執行計劃,同explain plan

5. 生成Trace文件查詢詳細的執行計劃 (SQL_Trace, 10046)
SQL_TRACE作為初始化參數可以在實例級別啟用,也可以只在會話級別啟用,在實例級別啟用SQL_TRACE會導致所有進程的活動被跟蹤,包括後台進程及所有用戶進程,這通常會導致比較嚴重的性能問題,所以在一般情況下,我們使用sql_trace跟蹤當前進程,方法如下:
SQL>alter session set sql_trace=true;
...被跟蹤的SQL語句...
SQL>alter session set sql_trace=false;
如果要跟蹤其它進程,可以通過Oracle提供的系統包DBMS_SYSTEM. SET_SQL_TRACE_IN_SESSION來實現,例如:
SQL> exec dbms_system.set_sql_trace_in_session(sid,serial#,true) --開始跟蹤
SQL> exec dbms_system.set_sql_trace_in_session(sid,serial#,false) --結束跟蹤
生成trace文件後,再用tkprof 工具將sql trace 生成的跟蹤文件轉換成易讀的格式,語法如下:
tkprof inputfile outputfile
10046事件是SQL_TRACE的一個升級版,它也是追蹤會話,生成Trace文件,只是它裡面的內容更詳細,

6. 什麼是sql執行計劃

執行計劃:就是一個sql語句執行數據的方式。
先採用何種方式操作 操作表,
採用那種順序操作表

7. SQL中的執行計劃具體內容介紹比如Cost ,Cardinality 等什麽意思啊謝謝!

1、set @SD = cast( (cast(@Month as varchar) + '-1- ' + cast(@year as varchar)) as datetime)

cost表示把一個字元串數據轉換為時間類型的數據.
2、表示優化中的基數