日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁西西教程數(shù)據(jù)庫教程 → Oracle SQL tuning 數(shù)據(jù)庫優(yōu)化步驟圖文教程

      Oracle SQL tuning 數(shù)據(jù)庫優(yōu)化步驟圖文教程

      相關(guān)軟件相關(guān)文章發(fā)表評論 來源:西西整理時間:2013/8/3 20:55:37字體大小:A-A+

      作者:西西點(diǎn)擊:11次評論:0次標(biāo)簽: SQLtuning

      SQL Turning 是Quest公司出品的Quest Central軟件中的一個工具。Quest Central是一款集成化、圖形化、跨平臺的數(shù)據(jù)庫管理解決方案,可以同時管理 Oracle、DB2 和 SQL server 數(shù)據(jù)庫。

      一、SQL Tuning for SQL Server簡介

      SQL語句的優(yōu)化對發(fā)揮數(shù)據(jù)庫的最佳性能非常關(guān)鍵。然而不幸的是,應(yīng)用優(yōu)化通常由于時間和資源的因素而被忽略。SQL Tuning (SQL優(yōu)化)模塊可以對比和評測特定應(yīng)用中SQL語句的運(yùn)行性能,提出智能化的優(yōu)化建議,幫助用戶改善應(yīng)用的響應(yīng)時間。SQL優(yōu)化模塊具有非介入式SQL采集、自動優(yōu)化和專家建議等功能,全面改善SQL優(yōu)化工作。

      二、SQL Tuning for SQL Server的使用

      1、打開Quest Database Management Solutions彈出窗口如圖1所示

      圖1  

      2、在紅色標(biāo)記處打開SQL Tuning 優(yōu)化SQL    

        (1)建立連接。

      在Quest Central主界面上的“Database”樹上選擇“SQL Server”,然后在下方出現(xiàn)的“Tools”框中選擇“SQL Tuning”選項,打開“Lanch SQL Tuning for SQL Server Connections”對話框(圖2、圖3)。我們在這里建立數(shù)據(jù)庫服務(wù)器的連接,以后的分析工作都會在它上面完成。 

      圖2 “建立連接”對話框 

      圖3

           雙擊“New Connection”圖標(biāo),在彈出窗口中輸入數(shù)據(jù)庫的信息,單擊“OK”,然后單擊“Connect”即可。

         (2)分析原始SQL語句 ,在單擊“Connect”后將彈出一個新窗口,如圖4 

      圖4

      在打開窗口的“Oriangal SQL”文本框內(nèi)輸入需要分析的原始SQL語句,紅色標(biāo)記處選擇對應(yīng)的數(shù)據(jù)庫名,SQL語句代碼如下:

      圖5 分析原始SQL語句

      原始SQL語句

      然后點(diǎn)擊工具欄上的“Execute”按鈕,執(zhí)行原始的SQL語句,SQL Tuning會自動分析SQL的執(zhí)行計劃,并把分析結(jié)果顯示到界面上(圖5)。

      (3)優(yōu)化SQL。

      現(xiàn)在我們點(diǎn)擊工具欄上的“Optimize Statement”按鈕,讓SQL Tuning開始優(yōu)化SQL,完成后,可以看到SQL Tuning產(chǎn)生了19條與原始SQL等價的優(yōu)化方案(圖6)。 

      圖6 SQL優(yōu)化方案

      (4)獲得最優(yōu)SQL。

      接下來,我們來執(zhí)行上面產(chǎn)生的優(yōu)化方案,以選出性能最佳的等效SQL語句。在列表中選擇需要執(zhí)行的優(yōu)化方案(默認(rèn)已全部選中),然后點(diǎn)擊工具欄上的“Execute”按鈕旁邊的下拉菜單,選擇“Execute Selected”。等到所有SQL運(yùn)行完成后,點(diǎn)擊界面左方的“Tuning Resolution”按鈕,
      可以看到最優(yōu)的SQL已經(jīng)出來啦,運(yùn)行時間竟然可以提高21%。▓D7)

      圖7 “Tuning Resolution”界面 

      最優(yōu)的SQL語句如下:

      5)學(xué)習(xí)書寫專家級的SQL語句 。

      優(yōu)化后的SQL語句

      SELECT dbo.Person_BasicInfo.*, 
             dbo.Graduater_GraduaterRegist.RegistNO AS RegistNO, 
             dbo.Graduater_GraduaterRegist.RegistTime AS BaoDaoTime, 
             dbo.Graduater_GraduaterRegist.RegistMan AS RegistMan, 
             dbo.Graduater_Business.ComeFrom AS ComeFrom, 
             dbo.Graduater_Business.Code AS Code, 
             dbo.Graduater_Business.Status AS Status, 
             dbo.Graduater_Business.ApproveResult AS ApproveResult, 
             dbo.Graduater_Business.NewCorp AS NewCorp, 
             dbo.Graduater_Business.CommendNumber AS CommendNumber, 
             dbo.Graduater_Business.EmployStatus AS EmployStatus, 
             dbo.Graduater_Business.NewCommendTime AS NewCommendTime, 
             dbo.Graduater_Business.GetSource AS GetSource, 
             dbo.Graduater_Business.EmployTime AS EmployTime, 
             dbo.Graduater_Business.Job AS Job, 
             dbo.Graduater_Business.FillMan AS FillMan, 
             dbo.Graduater_Business.FillTime AS FillTime, 
             dbo.Graduater_Business.IsCommendOK AS IsCommendOK, 
             dbo.Graduater_Business.ApproveUser AS ApproveUser, 
             dbo.Graduater_Business.ApproveTime AS ApproveTime, 
             dbo.Graduater_Business.RegistTime AS RegistTime, 
             dbo.Graduater_Business.EmployCorp AS EmployCorp, 
             dbo.Graduater_Business.JobRemark AS JobRemark, 
             CASE WHEN dbo.Graduater_Business.ComeFrom = 'WS' THEN '網(wǎng)上登記' 
                  WHEN dbo.Graduater_Business.ComeFrom = 'HP' THEN '華普大廈' 
                  WHEN dbo.Graduater_Business.ComeFrom = 'JD' THEN '精典大廈' 
                  WHEN dbo.Graduater_Business.ComeFrom = 'MC' THEN '賽馬場' 
                  WHEN ComeFrom = 'ZX' THEN '高指中心' END AS ComeFromName, 
             dbo.Person_Contact.Address AS Address, 
             dbo.Person_Contact.Zip AS Zip, 
             dbo.Person_Contact.Telephone AS Telephone, 
             dbo.Person_Contact.Mobile AS Mobile, 
             dbo.Person_Contact.Email AS Email, 
             dbo.Person_Contact.IM AS IM, 
             dbo.Person_Skill.ForeignLanguage AS ForeignLanguage, 
             dbo.Person_Skill.ForeignLanguageLevel AS ForeignLanguageLevel, 
             dbo.Person_Skill.CantoneseLevel AS CantoneseLevel, 
             dbo.Person_Skill.MandarinLevel AS MandarinLevel, 
             dbo.Person_Skill.Language AS Language, 
             dbo.Person_Skill.TechnicalTitle AS TechnicalTitle, 
             dbo.Person_Skill.ComputerLevel AS ComputerLevel, 
             dbo.Person_EmployPurpose.JobType AS JobType, 
             dbo.Person_EmployPurpose.Vocation AS Vocation, 
             dbo.Person_EmployPurpose.JobPlace AS JobPlace, 
             dbo.Person_EmployPurpose.Salary AS Salary, 
             dbo.Person_EmployPurpose.OnJobDate AS OnJobDate, 
             dbo.Person_EmployPurpose.CorpType AS CorpType, 
             dbo.Person_EmployPurpose.Job AS RequireJob, 
             YEAR(GETDATE()) - YEAR(dbo.Person_BasicInfo.Birthday) AS Age, 
             dbo.Graduater_Business.EmployType AS EmployType, 
             dbo.Graduater_Business.EmployTypeCode AS EmployTypeCode, 
             dbo.Graduater_Business.EmployCorpType AS EmployCorpType, 
             CASE WHEN dbo.Graduater_Business.PrintStatus = '已打印' THEN '已打印' 
                  ELSE '未打印' END AS PrintStatus, 
             dbo.Graduater_Business.PrintTime AS PrintTime, 
             CASE WHEN dbo.Graduater_Business.EmployStatus = '是' THEN '已就業(yè)' 
                  ELSE '未就業(yè)' END AS EmployStatusView 
        FROM dbo.Person_BasicInfo 
             INNER JOIN dbo.Graduater_Business 
                ON dbo.Person_BasicInfo.PersonID = dbo.Graduater_Business.PersonID 
             LEFT OUTER JOIN dbo.Graduater_GraduaterRegist 
               ON dbo.Graduater_Business.GradBusinessID = dbo.Graduater_GraduaterRegist.GraduaterGUID 
             INNER JOIN dbo.Person_Contact 
                ON dbo.Person_BasicInfo.PersonID = dbo.Person_Contact.PersonID 
             INNER JOIN dbo.Person_Skill 
                ON dbo.Person_BasicInfo.PersonID = dbo.Person_Skill.PersonID 
             INNER JOIN dbo.Person_EmployPurpose 
                ON dbo.Person_BasicInfo.PersonID = dbo.Person_EmployPurpose.PersonID 
      OPTION (FORCE ORDER)

       (

          通過上面的步驟,我們已經(jīng)可以實(shí)現(xiàn)自動優(yōu)化SQL語句,但更重要的是,我們還可以學(xué)習(xí)如何書寫這樣高性能的SQL語句。點(diǎn)擊界面左方的“Compare Scenarios”按鈕,我們可以比較優(yōu)化方案和原始SQL中的任意2條SQL語句,SQL Tuning會將它們之間的不同之處以不同顏色表示出來,
      還可以在下方的“執(zhí)行計劃”中,通過比較兩條SQL語句的執(zhí)行計劃的不同,來了解其中的差異(圖8)。 

      圖8 “Compare Scenarios”界面

      Oracle SQL tuning的目標(biāo)
          Oracle SQL tuning是一個復(fù)雜的課題。Oracle Tuning: The Definitive Reference 這整本書描述了關(guān)于SQL tuning的細(xì)節(jié)。盡管如此,
          為了提高系統(tǒng)系能,Oracle DBA應(yīng)當(dāng)遵從下面一些總的指導(dǎo)原則。

      1、SQL tuning 目標(biāo)
         是以最小的數(shù)據(jù)庫訪問次數(shù)提取更多地數(shù)據(jù)行來生成最佳的執(zhí)行計劃(盡可能最小化物理讀(PIO)與邏輯讀(LIO)。

          指導(dǎo)原則
              移除不必要的大型全表掃描
                  大型表的全表掃描將產(chǎn)生龐大的系統(tǒng)I/O且使得整個數(shù)據(jù)庫性能下降。優(yōu)化專家首先會評估當(dāng)前SQL查詢所返回的行數(shù)。最常見的辦
              法是為走全表掃描的大表增加索引。B樹索引,位圖索引,以及基于函數(shù)的索引等能夠避免全表掃描。有時候,對一些不必要的全表掃
              描通過添加提示的方法來避免全表掃描。

              緩存小表全表掃描
                  有時候全表掃描是最快的訪問方式,管理員應(yīng)當(dāng)確保專用的數(shù)據(jù)緩沖區(qū)(keep buffer cache,nk buffer cache)對這些表可用。在
                  Oracle 8 以后小表可以被強(qiáng)制緩存到 keep 池。

              使用最佳索引
                  Oracle 訪問對象有時候會有一個以上的索引選擇。因此應(yīng)當(dāng)檢查當(dāng)前查詢對象上的每一個索引以確保Oracle使用了最佳索引。

              物化聚合運(yùn)算以靜態(tài)化表統(tǒng)計
                  Oracle 10g的特性之一SQL Access advisor 會給出索引建議以及物化視圖的建議。物化視圖可以預(yù)連接表和預(yù)摘要表數(shù)據(jù)。(譯者
                  按,即Oracle可以根據(jù)特定的更新方式來提前更新物化視圖中的數(shù)據(jù),而在查詢時僅僅查詢物化視圖即可得到最終所需的統(tǒng)計數(shù)據(jù)
                  結(jié)果。物化視圖實(shí)際上是一張實(shí)體表)

          以上這些概括了SQL tuning的目標(biāo)。然而看是簡單,調(diào)整起來并不容易,因?yàn)檫@需要對Oracle SQL內(nèi)部有一個徹底的了解。接下來讓我們從
          整體上來認(rèn)識 Oracle SQL 優(yōu)化。

      2、Oracle SQL 優(yōu)化器
          Oracle DBA首先要查看的是當(dāng)前數(shù)據(jù)庫缺省的優(yōu)化器模式。Oracle初始化參數(shù)提供很多基于成本優(yōu)化的優(yōu)化器模式以及之前廢棄的基于規(guī)則
          的優(yōu)化器模式(或hint)供選擇。基于成本的優(yōu)化器主要依賴于表對象使用analyze命令收集的統(tǒng)計信息。Oracle根據(jù)表上的統(tǒng)計信息得以決定
          并為當(dāng)前的SQL生成最高效的執(zhí)行計劃。需要注意的是在一些場合基于成本優(yōu)化器可能會做出不正確的決定。基于成本的優(yōu)化器在不斷的改進(jìn),
          但是依然有很多場合使用基于規(guī)則的優(yōu)化器能夠使得查詢更高效。

          在Oracle 10g之前,Oracle 缺省的優(yōu)化器模式是CHOOSE模式。在該模式下,如果表對象上缺乏統(tǒng)計信息則此時Oracle使用基于規(guī)則的優(yōu)化
          器;如果統(tǒng)計信息存在則使用基于成本的優(yōu)化器。使用CHOOSE模式存在的隱患即是對一些復(fù)雜得查詢有些對象上有統(tǒng)計信息,而另一些對象
          缺乏統(tǒng)計信息。

          在Oracle 10g開始,缺省的優(yōu)化器模式是 ALL_ROWS,這有助于全表掃描優(yōu)于索引掃描。ALL_ROWS優(yōu)化器模式被設(shè)計成最小化計算資源且有
          助于全表掃描。索引掃描(first_rows_n)增加了額外的I/O開銷。但是他們能更快地返回數(shù)據(jù)。

      因此,大多數(shù)OLTP系統(tǒng)選擇first_rows,first_rows_100 或者 first_rows_10以使得Oracle使用索引掃描來減少讀塊數(shù)量。

          注意:從Oracle 9i R2開始,Oracle 性能調(diào)整指導(dǎo)指出了first_rows 優(yōu)化器模式已經(jīng)被廢棄,且使用first_rows_n代替

          當(dāng)僅有一些表包含CBO統(tǒng)計信息,而另一些缺乏統(tǒng)計信息時,Oracle使用基于成本的優(yōu)化模式來預(yù)估其他表在運(yùn)行時的統(tǒng)計信息(即動態(tài)采樣
          ),這在很大程度上影響單個查詢性能下降。

          總之,Oracle 數(shù)據(jù)庫管理員應(yīng)當(dāng)總是將嘗試改變優(yōu)化器模式作為SQL tuning的第一步。Oracle SQL tuning的首要原則是避免可怕的全表掃
          描。一個特性之一是一個非高效的SQL語句為提高查詢性能使用所有的索引此仍然為一個失敗的SQL語句。

          當(dāng)然,有些時候使用全表掃描是合適的,尤其是在做聚合操作象sum,avg等操作,因?yàn)闉榱双@得結(jié)果,表上的絕大部分?jǐn)?shù)據(jù)行必須被讀入到
          緩存。SQL tuning 高手應(yīng)當(dāng)合理的評估每一個全表掃描并要核實(shí)使用索引能否提高性能。

          在大多數(shù)Oracle 系統(tǒng),SQL語句檢索的僅僅是表上數(shù)據(jù)一個子集。Oracle 優(yōu)化器會檢查使用索引是否會導(dǎo)致更多的I/O。然而,如果構(gòu)建了
          一個低效的查詢,基于成本的優(yōu)化器難以選擇最佳的數(shù)據(jù)訪問路徑,轉(zhuǎn)而傾向于使用全表掃描。故Oracle數(shù)據(jù)庫管理員應(yīng)當(dāng)總是審查那些走
          全表掃描的SQL語句。

          更多有關(guān)全表掃描的問題,以及選擇正確的優(yōu)化模式請 :"Oracle Tuning: The Definitive Reference"

      三、SQL 調(diào)整戰(zhàn)略步驟
          很多人問SQL tuning從哪里著手。首先應(yīng)當(dāng)是從Library cache去根據(jù)他們的活動狀況捕獲SQL語句。

      1、尋找影響較大的SQL語句
          我們可以根據(jù)SQL語句執(zhí)行次數(shù)的多少進(jìn)行排序來獲得執(zhí)行次數(shù)較多的SQL語句。在v$sqlarea視圖中executions 列以及表stats$sql_summary
          或 dba_hist_sql_summary 能夠去定位當(dāng)前最頻繁使用的SQL語句。注:也可以按照下列方式列出SQL語句。
              Rows processed
                  處理的行數(shù)越多,則相應(yīng)會有很高的I/O,也有可能耗用大量的臨時表空間
               
              Buffer gets
                  Buffer gets過高可能表明資源被過度集中化查詢,存在熱塊現(xiàn)象
               
              Disk reads
                  高的磁盤讀將引起過度的I/O
               
              Memory KB
                  內(nèi)存的分配大小可以鑒別該SQL語句是否在內(nèi)存中使用了大量的表連接
               
              CPU secs
                  CPU的開銷表明哪些SQL語句耗用了大量的CPU資源
               
              Sorts
                  排序越多,則SQL性能越差,而且會占用大量的臨時表空間
               
              Executions
                  執(zhí)行次數(shù)表明了當(dāng)前SQL語句的頻繁度,應(yīng)當(dāng)被首先考慮調(diào)整,因?yàn)檫@些語句影響了數(shù)據(jù)庫的整體性能

      2、決定SQL的執(zhí)行計劃
          每一個SQL語句都可以根據(jù)SQL_ID來獲得其執(zhí)行計劃。有大量的第三方工具來獲得SQL語句的執(zhí)行計劃。而獲得執(zhí)行最常用的方式是使用Oracle
          自帶的explain plan程序。通過使用該程序,Oracle DBA能夠在不執(zhí)行SQL 語句的情形下解析并顯示該SQL語句的執(zhí)行計劃。

          查看SQL執(zhí)行計劃的輸出,必須首先創(chuàng)建一個plan table. Oracle提供一個utlxplan.sql腳本來創(chuàng)建該表。執(zhí)行該腳本并且為該表創(chuàng)建一個
          公共同義詞。

          sqlplus > @utlxplan
          Table created.
           
          sqlplus > create public synonym plan_table for sys.plan_table;
          Synonym created.

          大多數(shù)關(guān)系數(shù)據(jù)庫使用解釋程序?qū)QL語句作為輸入,然后運(yùn)行SQL優(yōu)化器,輸出訪問的路徑信息到一個plan_table。以便我們能夠查看及調(diào)
          整其訪問方式。下面的是一個復(fù)雜的SQL查詢。

          EXPLAIN PLAN SET STATEMENT_ID = 'test1' FOR
          SET STATEMENT_ID = 'RUN1'
          INTO plan_table
          FOR
          SELECT   'T'||plansnet.terr_code, 'P'||detplan.pac1
          || detplan.pac2 || detplan.pac3, 'P1', sum(plansnet.ytd_d_ly_tm),
           sum(plansnet.ytd_d_ty_tm),
           sum(plansnet.jan_d_ly),
           sum(plansnet.jan_d_ty),
          FROM plansnet, detplan
          WHERE
              plansnet.mgc = detplan.mktgpm
          AND
              detplan.pac1 in ('N33','192','195','201','BAI',
              'P51','Q27','180','181','183','184','186','188',
              '198','204','207','209','211')
          GROUP BY 'T'||plansnet.terr_code, 'P'||detplan.pac1 || detplan.pac2 || detplan.pac3;

          這個語法使用管道輸入到SQL優(yōu)化器,解析SQL,存儲執(zhí)行計劃信息到表plan_table,且RUN1作為鑒別當(dāng)前SQL語句的標(biāo)識符。注意,該查詢
          并沒有執(zhí)行,它僅僅是創(chuàng)建了一個內(nèi)部訪問信息且輸出到plan_table。plan 表包含下列字段。
          
              operation
                  表明當(dāng)前語句完成的操作,通常包括table access, table merge, sort, or index operation
               
              options
                  補(bǔ)充說明operation,像full table, range table, join
               
              object_name
                  查詢組件的名字
               
              Process ID
                  查詢組件的ID號
               
              Parent_ID
                  查詢組建的父ID,注意,有些查詢會有一個相同的父ID

          現(xiàn)在plan_table已經(jīng)被填充,可以使用下面的查詢來查看當(dāng)前SQL語句的執(zhí)行計劃。
          
              plan.sql - displays contents of the explain plan table
              SET PAGES 9999;
              SELECT  lpad(' ',2*(level-1))||operation operation,
                      options,
                      object_name,
                      position
              FROM plan_table
              START WITH id=0
              AND
              statement_id = 'RUN1'
              CONNECT BY prior id = parent_id
              AND
              statement_id = 'RUN1';

          下面給出了當(dāng)前語句執(zhí)行計劃信息以及各個部分的執(zhí)行順序。
          SQL> @list_explain_plan
           
          OPERATION
          -------------------------------------------------------------------------------------
          OPTIONS                           OBJECT_NAME                    POSITION
          ------------------------------ -------------------------------------------------------
          SELECT STATEMENT
          SORT
          GROUP BY                                                      1
                 CONCATENATION                                   1
          NESTED LOOPS                                    1
          TABLE ACCESS FULL         PLANSNET                   1
          TABLE ACCESS BY ROWID     DETPLAN                    2
                    INDEX RANGE SCAN       DETPLAN_INDEX5             1
          NESTED LOOPS
          
          從上面的執(zhí)行計劃中得知當(dāng)前的SQL語句存在表掃描現(xiàn)象。去調(diào)整該SQL語句,我們應(yīng)當(dāng)尋找表where 子句中為planset上的列。在這里我們
          看到了在where子句存在一個且屬于表planset上的列mgc被用作連接條件。這說明一個基于表planset.mgs列上的索引是必要的。

          plan table并不能展現(xiàn)整個SQL語句的細(xì)節(jié),但對于獲得數(shù)據(jù)訪問路徑是非常有用的。SQL優(yōu)化器知道每一個表的行數(shù)(基數(shù))以及一些索引字
          段的狀況。但并不了解數(shù)據(jù)的分布象如一個組件期待返回的行數(shù)。

      3、調(diào)整SQL語句
          對于那些存在可優(yōu)化的子執(zhí)行計劃,SQL應(yīng)當(dāng)按照下面的方式進(jìn)行調(diào)整。

          通過添加提示來修改SQL的執(zhí)行計劃

          使用全局臨時表來重寫SQL

          使用PL/SQL來重寫SQL。對于一些特定查詢該方法能夠有20倍左右的提升。將這些SQL封裝到包含存儲過程的包中去完成查詢。

          使用提示來調(diào)整SQL

          大多數(shù)SQL tuning工具中使用較多的莫過于使用提示。一個提示添加的SQL語句后使得SQL查詢的按指定路徑訪問。

          Troubleshooting tip! 
          為便于測試,我們能夠隨時使用alter session命令來修改一個優(yōu)化參數(shù)的值來觀察調(diào)整前后的結(jié)果比較。使用新的 opt_param 提示能獲得
          同樣的效果。
          
          select /*+ opt_param('optimizer_mode','first_rows_10') */ col1, col2 . . .
          select /*+ opt_param('optimizer_index_cost_adj',20) */ col1, col2 . .

          Oracle 發(fā)布了大量的SQL提示,而且提示隨著Oracle版本的不同不斷的增強(qiáng)和復(fù)雜化。

          注意:提示通常用于調(diào)試SQL,最佳的辦法是調(diào)整優(yōu)化器的統(tǒng)計信息使的CBO模式自動獲取最佳執(zhí)行路徑,等同于使用提示的功能。
          我們來看看提高性能最常用的提示

              Mode hints:  first_rows_10, first_rows_100
              Oracle leading and ordered hints  Also see how to tune table join order with histograms
               
              Dynamic sampling: dynamic_sampling
               
              Oracle SQL undocumented tuning hints - Guru's only
              The cardinality hint    
          
          表連接順序
              當(dāng)表連接的順序可優(yōu)化時,我們可以使用 ORDERED提示來強(qiáng)制表按照from子句中出現(xiàn)的先后順序來進(jìn)行連接
           
          first_rows_n提示
              Oracle 有兩個基于成本優(yōu)化的提示,一個是first_rows_n,一個是all_rows。first_rows模式將盡可能在一查詢到數(shù)據(jù)時就返回個客
              戶端。而 all_rows 模式則為優(yōu)化資源而設(shè)計,需要等到所有結(jié)果計算執(zhí)行完畢才返回數(shù)據(jù)給客戶端。
           
              SELECT /*+ first_rows */
           
      4、案例
          同一個SQL語句有不同的寫法。即簡單的SQL查詢能夠以不同的方式來產(chǎn)生相同的結(jié)果集,但其執(zhí)行效率和訪問方式則千差萬別。
           
          下面的例子中的SQL語句使用了3種不同的寫法來返回相同的結(jié)果
           
          A standard join:  -->標(biāo)準(zhǔn)連接
           
          SELECT *
          FROM STUDENT, REGISTRATION
          WHERE
              STUDENT.student_id = REGISTRATION.student_id
          AND
              REGISTRATION.grade = 'A';
           
          A nested query:  -->嵌套查詢

          SELECT *
          FROM STUDENT
          WHERE
              student_id =
              (SELECT student_id
                  FROM REGISTRATION
                  WHERE
                 grade = 'A'
              );

          A correlated subquery:  -->相關(guān)子查詢

          SELECT *
          FROM STUDENT
          WHERE
              0 <
              (SELECT count(*)
                  FROM REGISTRATION
                  WHERE
                  grade = 'A'
                  AND
                  student_id = STUDENT.student_id
              );
              
          我們應(yīng)該根據(jù)基本的SQL原則來優(yōu)化當(dāng)前的SQL語句。

      5、書寫高效SQL語句的技巧
              下面給出一些編寫高效SQL語句的總的指導(dǎo)原則,而不論Oracle優(yōu)化器選擇何種優(yōu)化模式。這些看是簡單的方式但是按照他們
          去做將收到事半功倍的效果(已經(jīng)在實(shí)踐中被證實(shí))。
              
          a.使用臨時表重寫復(fù)雜的子查詢
              Oracle 使用全局臨時表以及WITH操作符去解決那些復(fù)雜的SQL子查詢。尤其是那些where子句中的子查詢,SELECT 字句標(biāo)量子查詢,
              FROM 子句的內(nèi)聯(lián)視圖。使用臨時表實(shí)現(xiàn)SQL tuning(以及使用WITH的物化視圖)能夠使得性能得以驚人的提升。
              
          b.使用MINUS 代替EXIST子查詢
              使用MINUS操作代替NOT IN 或NOT EXISTS將產(chǎn)生更高效的執(zhí)行計劃(譯者按:此需要測試)。
              
          c.使用SQL分析函數(shù)
              Oracle 分析函數(shù)能夠一次提取數(shù)據(jù)來做多維聚合運(yùn)算(象ROLLUP,CUBE)以提高性能。
              
          d.重寫NOT EXISTS和查詢作為外部連接NOT EXISTS 子查詢
              在一些案例中的NOT 查詢(where 中一個列被定義為NULL值),能夠?qū)⑵涓膶戇@個非相關(guān)子查詢到IS NULL 的外部鏈接。如下例:
              select book_key from book
              where
              book_key NOT IN (select book_key from sales);

              下面我們在where子句中使用了外部連接來替代原來的not exits,得到一個更高效的執(zhí)行計劃。

              select b.book_key from book b, sales s
              where
                 b.book_key = s.book_key(+)
              and
                 s.book_key IS NULL;

          e.索引NULL值列
              如果你的SQL語句頻繁使用到NULL值,應(yīng)當(dāng)考慮基于NULL值創(chuàng)建索引。為使該查詢最優(yōu)化,可以創(chuàng)建一個使用基于NULL值索引函數(shù)。
              (譯者按,如 create index i_tb_col on tab(nvl(col,null)); create index i_tb_col on tab(col,0);)

          f.避免基于索引的運(yùn)算
              不要基于索引列做任何運(yùn)算,除非你創(chuàng)建了一個相應(yīng)的索引函數(shù);蛘咧卦O(shè)設(shè)計列以使得where子句列上的謂詞不需要轉(zhuǎn)換。
              -->下面都是低效的SQL寫法
              where salary*5            > :myvalue   
              where substr(ssn,7,4)     = "1234"
              where to_char(mydate,mon) = "january"

          g.避免使用NOT IN 和HAVING 
              在合適的時候使用not exists子查詢更高效。

          h.避免使用LIKE謂詞
              在合適地時候,如果能夠使用 = 運(yùn)算應(yīng)盡可能避免LIKE操作。

          i.避免數(shù)據(jù)類型轉(zhuǎn)換
              如果一個where 子句列是數(shù)字型,則不要使用引號。而對一個字符索引列,總是使用引號。下面是數(shù)據(jù)類型混用的情形。
              where cust_nbr = "123"
              where substr(ssn,7,4) = 1234

          j.使用decode與case
              使用decode 與case 函數(shù)能夠最小化查詢表的次數(shù)。

          k.不要害怕全表掃描
              并不是所有的OLTP系統(tǒng)在使用索引時是最優(yōu)化的。如果你的查詢返回了表中的絕大部分?jǐn)?shù)據(jù),則全表掃描性能優(yōu)于索引掃描。這取決于
              一些因素包括你的配置(db_file_multiblock_read_count, db_block_size),并行查詢,以及表塊和索引塊在buffer cache中的數(shù)量。

          l.使用別名
              在參照列的地方總是使用表別名。
          --> Author : Robinson Cheng
          --> Blog   : http://blog.csdn.net/robinson_0612

        相關(guān)評論

        閱讀本文后您有什么感想? 已有人給出評價!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評論

        最新評論

        發(fā)表評論 查看所有評論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)