oracle執行計划(Explain Plan for


  1 如果要分析某條SQL的性能問題,通常我們要先看SQL的執行計划,看看SQL的每一步執行是否存在問題。 如果一條SQL平時執行的好好的,卻有一天突然性能很差,如果排除了系統資源和阻塞的原因,那么基本可以斷定是執行計划出了問題。
  2 
  3       
  4 
  5        看懂執行計划也就成了SQL優化的先決條件。 這里的SQL優化指的是SQL性能問題的定位,定位后就可以解決問題。
  6 
  7  
  8 
  9  
 10 
 11 一.         查看執行計划的三種方法
 12 
 13 1.1 設置autotrace
 14 
 15 序號
 16 
 17 命令
 18 
 19 解釋
 20 
 21 1
 22 
 23 SET AUTOTRACE OFF
 24 
 25 此為默認值,即關閉Autotrace 
 26 
 27 2
 28 
 29 SET AUTOTRACE ON EXPLAIN
 30 
 31 只顯示執行計划
 32 
 33 3
 34 
 35 SET AUTOTRACE ON STATISTICS
 36 
 37  只顯示執行的統計信息
 38 
 39 4
 40 
 41 SET AUTOTRACE ON
 42 
 43  包含2,3兩項內容
 44 
 45 5
 46 
 47 SET AUTOTRACE TRACEONLY
 48 
 49  與ON相似,但不顯示語句的執行結果
 50 
 51  
 52 
 53 SQL> set autotrace on
 54 
 55 SQL> select * from dave;
 56 
 57         ID NAME
 58 
 59 ---------- ----------
 60 
 61          8 安慶
 62 
 63          1 dave
 64 
 65          2 bl
 66 
 67          1 bl
 68 
 69          2 dave
 70 
 71          3 dba
 72 
 73          4 sf-express
 74 
 75          5 dmm
 76 
 77  
 78 
 79 已選擇8行。
 80 
 81  
 82 
 83 執行計划
 84 
 85 ----------------------------------------------------------
 86 
 87 Plan hash value: 3458767806
 88 
 89 --------------------------------------------------------------------------
 90 
 91 | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
 92 
 93 --------------------------------------------------------------------------
 94 
 95 |   0 | SELECT STATEMENT  |      |     8 |    64 |     2   (0)| 00:00:01 |
 96 
 97 |   1 |  TABLE ACCESS FULL| DAVE |     8 |    64 |     2   (0)| 00:00:01 |
 98 
 99 --------------------------------------------------------------------------
100 
101  
102 
103 統計信息
104 
105 ----------------------------------------------------------
106 
107           0  recursive calls
108 
109           0  db block gets
110 
111           4  consistent gets
112 
113           0  physical reads
114 
115           0  redo size
116 
117         609  bytes sent via SQL*Net to client
118 
119         416  bytes received via SQL*Net from client
120 
121           2  SQL*Net roundtrips to/from client
122 
123           0  sorts (memory)
124 
125           0  sorts (disk)
126 
127           8  rows processed
128 
129  
130 
131 SQL>
132 
133  
134 
135 1.2 使用SQL
136 
137 SQL>EXPLAIN PLAN FOR sql語句;
138 
139 SQL>SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
140 
141  
142 
143 示例:
144 
145 SQL> EXPLAIN PLAN FOR SELECT * FROM DAVE;
146 
147 已解釋。
148 
149 SQL> SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
150 
151 或者:
152 
153 SQL>  select * from table(dbms_xplan.display);
154 
155 PLAN_TABLE_OUTPUT
156 
157 --------------------------------------------------------------------------------
158 
159 Plan hash value: 3458767806
160 
161  
162 
163 --------------------------------------------------------------------------
164 
165 | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
166 
167 --------------------------------------------------------------------------
168 
169 |   0 | SELECT STATEMENT  |      |     8 |    64 |     2   (0)| 00:00:01 |
170 
171 |   1 |  TABLE ACCESS FULL| DAVE |     8 |    64 |     2   (0)| 00:00:01 |
172 
173 --------------------------------------------------------------------------
174 
175 已選擇8行。
176 
177 執行計划
178 
179 ----------------------------------------------------------
180 
181 Plan hash value: 2137789089
182 
183 --------------------------------------------------------------------------------
184 
185 | Id  | Operation                         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
186 
187 ---------------------------------------------------------------------------------------------
188 
189 |   0 | SELECT STATEMENT                  |         |  8168 | 16336 |    29   (0)| 00:00:01 |
190 
191 |   1 |  COLLECTION ITERATOR PICKLER FETCH| DISPLAY |  8168 | 16336 |    29   (0)| 00:00:01 |
192 
193 ---------------------------------------------------------------------------------------------
194 
195  
196 
197 統計信息
198 
199 ----------------------------------------------------------
200 
201          25  recursive calls
202 
203          12  db block gets
204 
205         168  consistent gets
206 
207           0  physical reads
208 
209           0  redo size
210 
211         974  bytes sent via SQL*Net to client
212 
213         416  bytes received via SQL*Net from client
214 
215           2  SQL*Net roundtrips to/from client
216 
217           1  sorts (memory)
218 
219           0  sorts (disk)
220 
221           8  rows processed
222 
223 SQL>
224 
225  
226 
227 1.3 使用Toad,PL/SQL Developer工具
228 
229  
230 
231  
232 
233 二.         Cardinality(基數)/ rows
234 
235 Cardinality值表示CBO預期從一個行源(row source)返回的記錄數,這個行源可能是一個表,一個索引,也可能是一個子查詢。   在Oracle 9i中的執行計划中,Cardinality縮寫成Card。 在10g中,Card值被rows替換。
236 
237  
238 
239 這是9i的一個執行計划,我們可以看到關鍵字Card:
240 
241        執行計划
242 
243 ----------------------------------------------------------
244 
245    0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=402)
246 
247    1    0   TABLE ACCESS (FULL) OF 'TBILLLOG8' (Cost=2 Card=1 Bytes=402)
248 
249  
250 
251 Oracle 10g的執行計划,關鍵字換成了rows:
252 
253 執行計划
254 
255 ----------------------------------------------------------
256 
257 Plan hash value: 2137789089
258 
259 --------------------------------------------------------------------------------
260 
261 | Id  | Operation                         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
262 
263 ---------------------------------------------------------------------------------------------
264 
265 |   0 | SELECT STATEMENT                  |         |  8168 | 16336 |    29   (0)| 00:00:01 |
266 
267 |   1 |  COLLECTION ITERATOR PICKLER FETCH| DISPLAY |  8168 | 16336 |    29   (0)| 00:00:01 |
268 
269 ---------------------------------------------------------------------------------------------
270 
271  
272 
273 Cardinality的值對於CBO做出正確的執行計划來說至關重要。 如果CBO獲得的Cardinality值不夠准確(通常是沒有做分析或者分析數據過舊造成),在執行計划成本計算上就會出現偏差,從而導致CBO錯誤的制定出執行計划。
274 
275  
276 
277        在多表關聯查詢或者SQL中有子查詢時,每個關聯表或子查詢的Cardinality的值對主查詢的影響都非常大,甚至可以說,CBO就是依賴於各個關聯表或者子查詢Cardinality值計算出最后的執行計划。
278 
279  
280 
281        對於多表查詢,CBO使用每個關聯表返回的行數(Cardinality)決定用什么樣的訪問方式來做表關聯(如Nested loops Join 或 hash Join)。
282 
283           多表連接的三種方式詳解 HASH JOIN MERGE JOIN NESTED LOOP
284 
285               http://blog.csdn.net/tianlesoftware/archive/2010/08/20/5826546.aspx
286 
287  
288 
289 對於子查詢,它的Cardinality將決定子查詢是使用索引還是使用全表掃描的方式訪問數據。
290 
291  
292 
293  
294 
295  
296 
297 三. SQL 的執行計划
298 
299        生成SQL的執行計划是Oracle在對SQL做硬解析時的一個非常重要的步驟,它制定出一個方案告訴Oracle在執行這條SQL時以什么樣的方式訪問數據:索引還是全表掃描,是Hash Join還是Nested loops Join等。 比如說某條SQL通過使用索引的方式訪問數據是最節省資源的,結果CBO作出的執行計划是全表掃描,那么這條SQL的性能必然是比較差的。
300 
301        Oracle SQL的硬解析和軟解析
302 
303        http://blog.csdn.net/tianlesoftware/archive/2010/04/08/5458896.aspx
304 
305  
306 
307 示例:
308 
309 SQL> SET AUTOTRACE TRACEONLY;  -- 只顯示執行計划,不顯示結果集
310 
311 SQL> select * from scott.emp a,scott.emp b where a.empno=b.mgr;
312 
313 已選擇13行。
314 
315  
316 
317 執行計划
318 
319 ----------------------------------------------------------
320 
321 Plan hash value: 992080948
322 
323 ---------------------------------------------------------------------------------------
324 
325 | Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
326 
327 ---------------------------------------------------------------------------------------
328 
329 |   0 | SELECT STATEMENT             |        |    13 |   988 |     6  (17)| 00:00:01 |
330 
331 |   1 |  MERGE JOIN                  |        |    13 |   988 |     6  (17)| 00:00:01 |
332 
333 |   2 |   TABLE ACCESS BY INDEX ROWID| EMP    |    14 |   532 |     2   (0)| 00:00:01 |
334 
335 |   3 |    INDEX FULL SCAN           | PK_EMP |    14 |       |     1   (0)| 00:00:01 |
336 
337 |*  4 |   SORT JOIN                  |        |    13 |   494 |     4  (25)| 00:00:01 |
338 
339 |*  5 |    TABLE ACCESS FULL         | EMP    |    13 |   494 |     3   (0)| 00:00:01 |
340 
341 ---------------------------------------------------------------------------------------
342 
343  
344 
345 Predicate Information (identified by operation id):
346 
347 ---------------------------------------------------
348 
349    4 - access("A"."EMPNO"="B"."MGR")
350 
351        filter("A"."EMPNO"="B"."MGR")
352 
353    5 - filter("B"."MGR" IS NOT NULL)
354 
355  
356 
357 統計信息
358 
359 ----------------------------------------------------------
360 
361           0  recursive calls
362 
363           0  db block gets
364 
365          11  consistent gets
366 
367           0  physical reads
368 
369           0  redo size
370 
371        2091  bytes sent via SQL*Net to client
372 
373         416  bytes received via SQL*Net from client
374 
375           2  SQL*Net roundtrips to/from client
376 
377           1  sorts (memory)
378 
379           0  sorts (disk)
380 
381          13  rows processed
382 
383 SQL>
384 
385  
386 
387  
388 
389  
390 
391  
392 
393 圖片是Toad工具查看的執行計划。 在Toad 里面,很清楚的顯示了執行的順序。 但是如果在SQLPLUS里面就不是那么直接。 但我們也可以判斷:一般按縮進長度來判斷,縮進最大的最先執行,如果有2行縮進一樣,那么就先執行上面的。
394 
395  
396 
397  
398 
399 3.1 執行計划中字段解釋:
400 
401        ID: 一個序號,但不是執行的先后順序。執行的先后根據縮進來判斷。
402 
403        Operation: 當前操作的內容。
404 
405        Rows: 當前操作的Cardinality,Oracle估計當前操作的返回結果集。
406 
407        Cost(CPU):Oracle 計算出來的一個數值(代價),用於說明SQL執行的代價。
408 
409        Time:Oracle 估計當前操作的時間。
410 
411  
412 
413 3.2 謂詞說明:
414 
415 Predicate Information (identified by operation id):
416 
417 ---------------------------------------------------
418 
419    4 - access("A"."EMPNO"="B"."MGR")
420 
421        filter("A"."EMPNO"="B"."MGR")
422 
423    5 - filter("B"."MGR" IS NOT NULL)
424 
425  
426 
427        Access: 表示這個謂詞條件的值將會影響數據的訪問路勁(表還是索引)。
428 
429        Filter:表示謂詞條件的值不會影響數據的訪問路勁,只起過濾的作用。
430 
431  
432 
433 在謂詞中主要注意access,要考慮謂詞的條件,使用的訪問路徑是否正確。
434 
435  
436 
437  
438 
439 3.3 統計信息說明:
440 
441  
442 
443  
444 
445  
446 
447 db block gets : 從buffer cache中讀取的block的數量    
448 
449 consistent gets: 從buffer cache中讀取的undo數據的block的數量    
450 
451 physical reads: 從磁盤讀取的block的數量    
452 
453 redo size: DML生成的redo的大小    
454 
455 sorts (memory) :在內存執行的排序量    
456 
457 sorts (disk) :在磁盤上執行的排序量    
458 
459  
460 
461        Physical Reads通常是我們最關心的,如果這個值很高,說明要從磁盤請求大量的數據到Buffer Cache里,通常意味着系統里存在大量全表掃描的SQL語句,這會影響到數據庫的性能,因此盡量避免語句做全表掃描,對於全表掃描的SQL語句,建議增 加相關的索引,優化SQL語句來解決。
462 
463  
464 
465 關於physical reads ,db block gets 和consistent gets這三個參數之間有一個換算公式:
466 
467        數據緩沖區的使用命中率=1 - ( physical reads / (db block gets + consistent gets) )。
468 
469  
470 
471 用以下語句可以查看數據緩沖區的命中率:
472 
473        SQL>SELECT name, value FROM v$sysstat WHERE name IN ('db block gets', 'consistent gets','physical reads');
474 
475        查詢出來的結果Buffer Cache的命中率應該在90%以上,否則需要增加數據緩沖區的大小。
476 
477  
478 
479 Recursive Calls:  Number of recursive calls generated at both the user and system level.    
480 
481 Oracle Database maintains tables used for internal processing. When it needs to change these tables, Oracle Database generates an internal SQL statement, which in turn generates a recursive call. In short, recursive calls are basically SQL performed on behalf of your SQL. So, if you had to parse the query, for example, you might have had to run some other queries to get data dictionary information. These would be recursive calls. Space management, security checks, calling PL/SQL from SQL—all incur recursive SQL calls。
482 
483  
484 
485 DB Block Gets: Number of times a CURRENT block was requested.
486 
487 Current mode blocks are retrieved as they exist right now, not in a consistent read fashion. Normally, blocks retrieved for a query are retrieved as they existed when the query began. Current mode blocks are retrieved as they exist right now, not from a previous point in time. During a SELECT, you might see current mode retrievals due to reading the data dictionary to find the extent information for a table to do a full scan (because you need the "right now" information, not the consistent read). During a modification, you will access the blocks in current mode in order to write to them. (DB Block Gets:請求的數據塊在buffer能滿足的個數)
488        當前模式塊意思就是在操作中正好提取的塊數目,而不是在一致性讀的情況下而產生的塊數。正常的情況下,一個查詢提取的塊是在查詢開始的那個時間點上存在的數據塊,當前塊是在這個時刻存在的數據塊,而不是在這個時間點之前或者之后的數據塊數目。
489 
490  
491 
492 Consistent Gets: Number of times a consistent read was requested for a block.
493 
494 This is how many blocks you processed in "consistent read" mode. This will include counts of blocks read from the rollback segment in order to roll back a block. This is the mode you read blocks in with a SELECT, for example. Also, when you do a searched UPDATE/DELETE, you read the blocks in consistent read mode and then get the block in current mode to actually do the modification. (Consistent Gets: 數據請求總數在回滾段Buffer中的數據一致性讀所需要的數據塊)
495        這里的概念是在處理你這個操作的時候需要在一致性讀狀態上處理多少個塊,這些塊產生的主要原因是因為由於在你查詢的過程中,由於其他會話對數據塊進行操 作,而對所要查詢的塊有了修改,但是由於我們的查詢是在這些修改之前調用的,所以需要對回滾段中的數據塊的前映像進行查詢,以保證數據的一致性。這樣就產 生了一致性讀。
496 
497  
498 
499 Physical Reads: Total number of data blocks read from disk. This number equals the value of "physical reads direct" plus all reads into buffer cache. (Physical Reads:實例啟動后,從磁盤讀到Buffer Cache數據塊數量)
500 
501 就是從磁盤上讀取數據塊的數量,其產生的主要原因是:
5021) 在數據庫高速緩存中不存在這些塊
5032) 全表掃描
5043) 磁盤排序
505 它們三者之間的關系大致可概括為:
506        邏輯讀指的是Oracle從內存讀到的數據塊數量。一般來說是'consistent gets' + 'db block gets'。當在內存中找不到所需的數據塊的話就需要從磁盤中獲取,於是就產生了'physical reads'507 
508  
509 
510 Sorts(disk):
511 
512     Number of sort operations that required at least one disk write. Sorts that require I/O to disk are quite resource intensive. Try increasing the size of the initialization parameter SORT_AREA_SIZE.
513 
514  
515 
516 bytes sent via SQL*Net to client:
517     Total number of bytes sent to the client from the foreground processes.
518 
519  
520 
521 bytes received via SQL*Net from client:
522     Total number of bytes received from the client over Oracle Net.
523 
524  
525 
526 SQL*Net roundtrips to/from client:
527     Total number of Oracle Net messages sent to and received from the client.
528 
529  
530 
531  
532 
533  
534 
535  
536 
537 更多內容參考Oracle聯機文檔:
538 
539        Statistics Descriptions
540 
541        http://download.oracle.com/docs/cd/E11882_01/server.112/e10820/stats002.htm#i375475
542 
543  
544 
545  
546 
547 3.4 動態分析
548 
549        如果在執行計划中有如下提示:
550 
551               Note
552 
553               ------------
554 
555                      -dynamic sampling used for the statement
556 
557       
558 
559        這提示用戶CBO當前使用的技術,需要用戶在分析計划時考慮到這些因素。 當出現這個提示,說明當前表使用了動態采樣。 我們從而推斷這個表可能沒有做過分析。
560 
561  
562 
563  
564 
565 這里會出現兩種情況:
566 
5671)       如果表沒有做過分析,那么CBO可以通過動態采樣的方式來獲取分析數據,也可以或者正確的執行計划。
568 
5692)       如果表分析過,但是分析信息過舊,這時CBO就不會在使用動態采樣,而是使用這些舊的分析數據,從而可能導致錯誤的執行計划。
570 
571  
572 
573  
574 
575  
576 
577 總結:
578 
579        在看執行計划的時候,除了看執行計划本身,還需要看謂詞和提示信息。 通過整體信息來判斷SQL 效率。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM