北工大計算機學院軟件工程研究所 程穎
          目前,幾乎所有的應用程序都要和數據庫打交道。通過查詢數據庫可很容易地獲得想
          要的數據。但是,令人不滿意的是:某些查詢時間長,響應速度慢。究其原因,一是硬件設
          備(如CPU、磁盤)的存取速度跟不上,內存容量不夠大,這需要計算機制造商的努力;另一
          方面是沒有進行查詢優化。本文就查詢優化問題,談點實踐體會。
          分解查詢
          這種方法是把查詢分解執行,根據付出開銷的多少來決定如何分解,如何執行。
          為方便敘述,先給出一個例子。
          關系:SUPPLIER(S#,SNAME,CITY)
           :S
          PARTS  (P#,PNAME,SIZE)
           :P
          PROJECT (J#,JNAME,COLOR)
          :J
          INVENTORY(S#,P#,QO)
          :V
          SUPPLY(S#,J#,P#,QU)
          :Y
          其中,QO:現有數量
          QU:要用的數量
          這個查詢是找出某城市能提供黑色轎車,且供應量大于1000的供應商名單。
          1. 一般查詢方法
          (1) 形成卡氏積 S×P×J×V×Y;
          (2) 從卡氏積中選擇出滿足條件的元組;
          (3) 在S.SNAME上投影。
          這是個5元查詢。當查詢涉及到卡氏積時,卡氏積的元組數將組合性增長,這樣不僅需
          要大量的存儲空間,而且執行查詢時間很長。
          2. 優化查詢方法
          該方法是把查詢分解處理。這里介紹兩種方法:
          (1) 一元子查詢提取
          任一N元查詢Q(X1,X2......Xn)被替換為一個一元查詢Q1和一個在其后執行的Q2,即
          Q→(Q1,Q2)。
          (2) 化簡
          Q被替換為兩個查詢Q1和Q2,Q2在Q1執行后執行,它們只有一個變化,即
          Q1(X1,X2......Xm), Q2(Xm,Xm+1......Xn)。
          例如上例的查詢可以分成兩個一元查詢
          SELECT P#
          FROM P
          WHERE P.PNAME=‘轎車’ AND P.COLOR=‘黑色’

          SELECT S#,J#,P#,QO
          FROM Y
          WHERE V.QO>1000
          另一部分查詢為:
          SELECT S.SNAME
          FROM S,P,J,V,Y
          WHERE (S.S#=V.S# AND S.S#=Y.S# AND
            S.CITY=J.CITY AND P.P#=V.P# AND
            T.P#=V.P# AND J.J#=Y.J#)
          上面例子的查詢也很容易化簡化為一個涉及(P,V)的查詢和在其后執行的涉及(S,J,
          Y,V)的查詢:
          SELECT S.SNAME
          FORM S,J,V,Y
          WHERE S.CITY=J.CITY AND S.S#=Y.S# AND
            J.J#=Y.J# AND V.QO>1000 AND P.#=Y.P#
          AND V.S#=Y.S# AND
           V.P#=(SELECT V.P#
            FROM  V,P
          WHERE V.P#=P P#AND P.PNAME=‘轎車’ AND P.COLOR=‘黑色’)
          3. 綜上所述
          ·一元子查詢提取幾乎總會得到好處,因為在關系運算之前盡可能減少關系的體積對
          減少相應的系統開銷起很大的作用;
          ·通常會得到期待的優化結果,但也并不絕對如此。
          選擇最優存取路徑
          在計算查詢表達式值時要充分考慮索引、數據的存儲分布等存取路徑,以進一步提高
          查詢效率。例如,選擇字段、連接字段上是否有索引,利用索引和HASHING算法可快速地存
          取包含索引屬性特定值的記錄。建立索引,用戶可按順序讀文件中的記錄,依照接近于物
          理順序的順序讀文件中的記錄是非常有效的。這種接近的物理順序讀取文件中記錄的索
          引稱為聚簇索引。聚簇索引使我們可利用存儲塊中的記錄物理聚簇的優點,加快查詢速度
          。下面具體談一點實踐體會。
          前不久,筆者參加了一個在國內開發的國外數據庫應用系統的編程工作。該系統后臺
          使用Oracle 7.3數據庫,Oracle的DBMS處理SQL執行語句的順序如下:
          (1) 根據WHERE子句選擇行;
          (2) 根據GROUP BY子句對這些行進行聚合;
          (3) 對每一分組用組函數計算結果;
          (4) 根據HAVING子句選擇和排除分組;
          (5) 根據ORDER BY子句中的組函數所得的結果對組進行排序。
          這是一個體現查詢優化思路的執行順序,它對查詢的性能具有直接影響。一般來說,
          被WHERE子句濾去的記錄越多,查詢速度就越快。因為減少了在GROUP BY運算中必須處理
          的行數量。在這次工作中筆者的體會如下。
          1. 盡量避免連接
          例如:
          PowerBuilder 5.0數據窗口在選擇庫表時自動把各個表中的相同屬性名(域也相同)
          連接起來,如圖所示:
          @@0644900.JPG;圖1@@
          這種自動連接多數情況下是有益的,但有些情況卻需要取消連接。如查詢條件為P20
          00、P3000、P4000的有效區分都為1,這時有兩種方法:
          (1) WHERE(P2000.有效區分=P3000.有效區分
            P3000.有效區分=P4000.有效區分
          P2000.有效區分=1
          )
          (2) WHERE(P2000.有效區分=1
          P3000.有效區分=1
          P4000.有效區分=1
          )
          第一種方法在自動生成的基礎上添加P2000.有效區分=1就可以了,第二種方法先要取
          消連接,然后再重新寫WHERE語句。表面看,第一種方法簡單,其實第一種方法大大降低了
          執行效率,因為它有不必要的連接。所以筆者在這里提醒使用者,不要為了一時省事而降
          低了系統的效率。
          2. 選擇最佳的解決方案
          解決同一問題的方法固然很多,但應用中應該選擇最佳的解決方法。例如,對某一問
          題的數據庫查詢有兩種方法,執行結果一樣,效率卻不同。
          這個問題是這樣的:
          @@0644901.JPG;圖2@@
          查詢要求是:如果在程序運行界面上輸入了負責人代碼(放到code中),那么將查詢P2
          000表中負責人代碼等于code的負責人名;如果沒有輸入負責人代碼,那么查詢P2000表中
          所有負責人名。負責人代碼的取值范圍是0~9999,兩種解決方法分別是:
          (1) IF 沒有輸入負責人代碼 THEN
          code1=0
          code2=9999
          ELSE
          code1=code2=負責人代碼
          END IF
          執行SQL語句為:
          SELECT 負責人名
          FROM P2000
          WHERE 負責人代碼>=:code1 AND負責人代碼
            <=:code2
          (2) IF 沒有輸入負責人代碼 THEN
            執行SQL語句為:
           SELECT 負責人名
          FROM P2000
          ELSE
          code= 負責人代碼
          執行SQL語句為:
          SELECT 負責人代碼
          FROM P2000
          WHERE 負責人代碼=:code
          END IF
          第一種方法只用了一條SQL語句,第二種方法用了兩條SQL語句。在沒有輸入負責人代
          碼時,第二種方法顯然比第一種方法執行效率高,因為它沒有限制條件;在輸入了負責人代
          碼時,第二種方法仍然比第一種方法效率高,不僅是少了一個限制條件,還因相等運算是最
          快的查詢運算。分析到這里,讀者優劣自明。
          此外,Oracle提供存儲過程功能,它是編譯好、優化過、且存儲在數據庫中的SQL語句
          和控制流語言的集合,如果利用好存儲過程,可極大地增強SQL語言的功能、效率和靈活性

          以上著重從實現的角度討論了查詢優化,實際上要想根本解決查詢優化問題,還需從
          設計上進行優化,如盡量使用大的內存,數據可適度冗余,庫結構優化,對于頻繁使用的表
          建立索引,面向對象的數據庫設計方法等等。
          posted on 2008-09-20 16:01 李威威 閱讀(180) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
           
          主站蜘蛛池模板: 和平县| 武城县| 吉木乃县| 肥东县| 新田县| 迁西县| 汶川县| 奉新县| 巫山县| 巴楚县| 寻甸| 锦州市| 新蔡县| 炉霍县| 读书| 安国市| 灵台县| 镇巴县| 伊吾县| 名山县| 麻城市| 光泽县| 右玉县| 石阡县| 临沧市| 九龙县| 集安市| 拉萨市| 罗平县| 万山特区| 绥化市| 堆龙德庆县| 江北区| 昌图县| 阳山县| 巧家县| 韩城市| 安塞县| 仁布县| 澄迈县| 改则县|