oracle sql優化總結

1.oracle優化器種類html

 自從ORACLE 10g以來,oracle就存在了兩種優化器--CBO和RBO。sql

    RBO: Rule-Based Optimization 基於規則的優化器數據庫

     CBO: Cost-Based Optimization 基於代價的優化器緩存

 RBO顧名思義,oracle在系統內部定義了一系列sql語句執行了規則,sql嚴格按照規則來生成執行計劃,並執行,對錶的數據分佈和變化不敏感,因此纔有了CBO的出現。服務器

 CBO是對每一個查詢所耗費的資源進行量化,從而能夠根據這個量化的值選出最佳的執行計劃,一個查詢所耗費的資源可分爲:I/O,CPU,network三部分代價。網絡

 <1>I/O通常是將數據庫文件中的數據庫塊讀入內存(磁盤讀入內存)所耗費的資源
session

 <2>CPU代價是內存中處理數據的代價,在這些數據上進行排序sort,表的join鏈接操做,這都須要cpu資源的耗費。oracle

 <3>network是遠程查詢數據庫表或者執行分佈式鏈接的網絡傳輸代價分佈式

注:oracle中數據庫的概念是oracle數據文件中的最小單位,由多個操做系統塊組成。ide

 數據庫使用的優化器根據參數optimizer_mode決定,取值以下:

  • RULE 使用RBO優化器

  • choose 數據字典有被引用的對象的統計數據,則使用CBO,不然使用RBO

  • all_rows 以數據吞吐量爲主要目標,以便使用最少的資源完成語句

  • first_rows 以數據響應時間爲主要目標,以便快速查詢開始的n行數據

  • first_rows[1|100|1000|n] 讓優化器選一個能把響應時間減到最小的執行計劃,以迅速產生查詢結果的前n行


2.執行計劃中的概念

  • row_sources(行源) 根據where中條件限制後的結果集或者多表連接後的結果集,不單指table

  • predicate(謂詞)

  •  access謂詞 這個謂詞的條件的值將會影響數據的訪問路徑(通常針對索引)

  •  fileter謂詞 起過濾做用 

  • driving table(驅動表,外表,outer table) 用於嵌套鏈接和哈希鏈接

  • probed table(被探查表,內表,inner table)

  • access path(訪問路徑)

  •  full table scans(全表掃描) oracle順序讀取分配給表的每一個數據塊,知道表的最高水位線。能夠一次性讀取多個塊,block的數量則由操做系統的I/O最大值和multiblock(db_block_multiblock_read_count)參數共同決定

  •    Table Access by ROWID(經過ROWID的表存取/rowid lookup)

  •    Index Scan(索引掃描/index lookup)

    ......

  • sort-mergejoin(排序合併鏈接)

  • nested loop(嵌套鏈接)

  • hash join(哈希鏈接)


3.sql語句執行過程

 每種類型sql語句都要一下n個階段:

 <1>create a cursor

 <2>parse the statement解析語句 

   判斷語法是否正確,權限是否充足,查找數據字典是否符合表,列的定義,鎖分析,生成執行計劃等,這一步驟比較耗費資源,通常都應該減小解析次數。可是也有下述這種狀況:當sql的基表發生的dml語句致使數據分佈發生了較大的變化(可能影響的執行計劃),若是還採用以前的執行計劃,有可能性能會不太好,這時候最好從新進行表分析,從新生成執行計劃,因此這個仍是要看具體狀況決定。

 <5>bind any variables

 <7>run the statement

 <9>close the cursor

若使用了並行功能

<6>parallelize the statement 並行執行語句

如果select語句

<3>describe result of a query 描述查詢結果集

<4>define output of a query 定義查詢輸出

<8>fetch rows of a query 獲取查詢行


4.sql中標的鏈接方式

 排序合併鏈接

 wKiom1i8JeiDSiieAAAfdGgzAqI381.png-wh_50

  1. row_source1按照鏈接列進行排序,row_source2按照鏈接列進行排序

  2. row_source1,row_source2一塊兒執行合併操做,即將兩個row_source按照鏈接條件鏈接起來


 嵌套循環

通常原則是選擇驅動表是較小的row_source

優勢:能夠快速返回已經鏈接的行,沒必要等全部行鏈接操做處理完才返回數據,可實時響應


 hash鏈接

較小的row_source用來構建hash table的bitmap,第二個row_source被用來hansed,並與第一個row_source生成的hash table匹配,以便進一步鏈接,比bitmap用來check hash table中是否有匹配的行。


三種鏈接方式比較:

smj:第一,對於非等值鏈接效率較高。關聯列上有索引更好。對於兩個較大的row_source比nl效率高

nl:第一快速響應。外部表較小,內部表上有惟一索引/高效的非惟一索引

hj:hash_area_size參數要合適。只能用於等值鏈接。


5.hints

 /*+ ordered*/:form子句從左到右順序鏈接

 /*+ full(table)*/:全表掃描

 /*+ index_ffs(table [index_name])*/:快速全表掃描

 /*+ no_index(table [index])*/不使用索引

 /*+ use_nl(table[,table...])*/ 嵌套循環

  例:use_nl(a c)此時a是內部表,c是驅動表

此外有外關聯的表不能做爲驅動表。若外關聯與ordered指定的順序有衝突,則忽略ordered hint


6.trace的使用


SELECT ss.SID,
       ss.SERIAL#,  --1.sid和serial#共同表示惟一一個session
       ss.USERNAME, --2.數據庫用戶名
       ss.MACHINE,  --3.鏈接數據庫所在程序的機器名,以下圖
       ss.PROGRAM, --鏈接數據庫的程序名
       p.SPID as serverid,--與程序對應的server段的服務器進程號,在unix中較有用
       ss.SERVER,    --程序鏈接數據庫模式:DEDICATED專用模式(trace只適用該模式)。shared
                     --共享模式
       ss.LOGON_TIME --鏈接數據庫的登陸時間
  FROM v$session ss, v$process p
 WHERE p.ADDR = ss.PADDR
   AND ss.USERNAME = 'SYS';

3 -->wKiom1jH71jB_Fr7AACZwlkvQY0822.png-wh_50


使用trace過程:

  1. 識別要跟蹤的client程序到數據庫的鏈接,上述sql可查

  2. 設定相應的parameter

    time_statistics 收集trace信息時,是否收集時間信息,能夠知道一個sql各階段耗時狀況

    user_dump_dest 存放跟蹤的文件位置

    max_dump_file_size 配置跟蹤文件的最大值

  使用procedure設置參數

exec dbms_system.set_bool_param_in_session(sid => '65',
                      seria# => '55',
                      parnam => 'time_statistics',
                      bval => true);

wKiom1jH9oiTqjoqAABj0Uisk7U429.png-wh_50

exec dbms_system.set_int_param_in_session(sid => '65',
                     seria# => '55',
                     parnam => 'user_dump_dest',
                     intval => true)


3.啓用跟蹤功能

exec dbms_system.set_sql_trace_in_session(8,3,true);


4.run一段時間


5.關閉trace

exec dbms_system.set_sql_trace_in_session(8,3,false);


6.格式化文件

tkprof xxx.trc xx.out sys=no explain=scott/tiger

TKPROF  filename1, filename2 [ SORT  = [ opion][,option] ]
  [  PRINT = integer ]
  [ AGGREGATE  = [ YES | NO ] ]
  [ INSERT = filename3 ]
  [ SYS = [ YES | NO ]  ]
  [  [ TABLE = schema.table ] | [ EXPLAIN = user/password ]  ]
  [  RECORD = filename ]

參數解析

SORT     在輸出到輸出文件前,先進程排序。若是省去,則按照實際使用的順序輸出到文件中。排序選項有如下多種:
  prscnt  number of times parse was called
  prscpu  cpu time parsing
  prsela  elapsed time parsing
  prsdsk  number of disk reads during parse
  prsqry  number of buffers for consistent read during parse
  prscu   number of buffers for current read during parse
  prsmis  number of misses in library cache during parse
  execnt  number of execute was called
  execpu  cpu time spent executing
  exeela  elapsed time executing
  exedsk  number of disk reads during execute
  exeqry  number of buffers for consistent read during execute
  execu   number of buffers for current read during execute
  exerow  number of rows processed during execute
  exemis  number of library cache misses during execute
  fchcnt  number of times fetch was called
  fchcpu  cpu time spent fetching
  fchela  elapsed time fetching
  fchdsk  number of disk reads during fetch
  fchqry  number of buffers for consistent read during fetch
  fchcu   number of buffers for current read during fetch
  fchrow  number of rows fetched
  userid  userid of user that parsed the cursor
PRINT        只列出輸出文件的第一個integer 的SQL語句。默認爲全部的SQL語句。
AGGREGATE    若是= NO ,則不對多個相同的SQL進行彙總。
INSERT       SQL 語句的一種,用於將跟蹤文件的統計信息存儲到數據庫中。在TKPROF建立腳本後,在將結果輸入到數據庫中。
SYS         禁止或啓用 將SYS用戶所發佈的SQL語句列表到輸出文件中。
TABLE       在輸出到輸出文件前,用於存放臨時表的用戶名和表名。
EXPLAIN     對每條SQL 語句肯定其執行規劃。並將執行規劃寫到輸出文件中。
   其中比較有用的一個排序選項是fchela,即按照elapsed time fetching來對分析的結果排序
(記住要設置初始化參數timed_statistics=true),生成的文件將把最消耗時間的sql放在最前面顯示。
另一個有用的參數就是sys,這個參數設置爲no能夠阻止全部以sys用戶執行的sql被顯示出來,
這樣能夠減小分析出來的文件的複雜度,便於查看。
首先解釋輸出文件中列的含義:
CALL:每次SQL語句的處理都分紅三個部分
Parse:這步將SQL語句轉換成執行計劃,包括檢查是否有正確的受權和所須要用到的表、列以及其餘引用到的對象是否存在。
Execute:這步是真正的由Oracle來執行語句。對於insert、update、delete操做,這步會修改數據,對於select操做,這步就只是肯定選擇的記錄。
Fetch:返回查詢語句中所得到的記錄,這步只有select語句會被執行。
COUNT:這個語句被parse、execute、fetch的次數。
CPU:這個語句對於全部的parse、execute、fetch所消耗的cpu的時間,以秒爲單位。
ELAPSED:這個語句全部消耗在parse、execute、fetch的總的時間。
DISK:從磁盤上的數據文件中物理讀取的塊的數量。通常來講更想知道的是正在從緩存中讀取的數據而不是從磁盤上讀取的數據。
QUERY:在一致性讀模式下,全部parse、execute、fetch所得到的buffer的數量。一致性模式的buffer是用於給一個長時間運行的事務提供一個一致性讀的快照,緩存實際上在頭部存儲了狀態。
CURRENT:在current模式下所得到的buffer的數量。通常在current模式下執行insert、update、delete操做都會獲取buffer。在current模式下若是在高速緩存區發現有新的緩存足夠給當前的事務使用,則這些buffer都會被讀入了緩存區中。
ROWS: 全部SQL語句返回的記錄數目,可是不包括子查詢中返回的記錄數目。對於select語句,返回記錄是在fetch這步,對於insert、update、delete操做,返回記錄則是在execute這步。


-----------------------------舉例---------------------

tkprof是在cmd下執行!!

相關文章
相關標籤/搜索