Oracle優化整理2

目前數據庫優化需要注意的幾點問題

 

1. 適當增加索引,儘可能使用已有的索引字段

:

SELECT count(*) AS record_count

    FROM (SELECT resume_id, name, gender, substr((sysdate - birthday) / 365, 1,

                 2) AS age, whcd_id, resident_area

              FROM z_resumes

              WHERE 1 = 1

                AND resident_area = '010'

                AND whcd_id = '30'

                AND substr((sysdate - birthday) / 365, 1, 2) = 25);

增加索引idx_z_resumes_resident_area on z_resumes (resident_area)

 

:

SELECT cid FROM       insu_comp_baseinfo WHERE       zzjgdm = :1

增加索引idx_insu_comp_zzjgdm on CITQUERY.insu_comp_baseinfo (zzjgdm)

 

:

select *

    from z_companies

    where short_name = '愛筵餐飲'

增加索引IDX_Z_COMPANIES_SHORTNAME ON Z_COMPANIES (SHORT_NAME)

 

對部分語句建議使用索引字段

如:

select *

from sysm_busilog

where user_name = :"SYS_B_0"

and to_char(time,:"SYS_B_1") = :"SYS_B_2"

建議在類似上述的SQL語句中,user_id替換user_name,減少對的全表掃描,因爲user_id字段上建有索引

 

 

2. 索引字段不要用函數或表達式作用,否則將不使用索引

:

SELECT WHCD

    FROM PERSON_INFO 

    WHERE UPPER(ZJHM) = :b1

建議去掉UPPER函數,改爲ZJHM = :b1

 

:

SELECT COMPANIES.COMPANY_ID AS COMPANY_ID,

    COMPANIES.REGISTER_COMPANY_CODE AS REGISTER_COMPANY_CODE,

    CORPORATION.DWQC AS NAME,COMPANIES.MAN_IN_CHARGE AS

    MAN_IN_CHARGE,COMPANIES.CONTACT_ADDRESS AS CONTACT_ADDRESS,

    COMPANIES.POSTAL_CODE AS POSTAL_CODE,COMPANIES.DWLB_ID AS

    DWLB_ID,COMPANIES.DWLX_ID AS DWLX_ID,

    COMPANIES.REGISTER_ADDRESS AS REGISTER_ADDRESS,

    COMPANIES.EMPLOYEE AS EMPLOYEE,COMPANIES.REGISTER_FUND AS

    REGISTER_FUND,COMPANIES.REGISTER_YEAR_LIMIT AS

    REGISTER_YEAR_LIMIT,COMPANIES.CONTACT_MAN AS CONTACT_MAN,

    COMPANIES.TELEPHONE AS TELEPHONE,COMPANIES.INVESTORS AS

    INVESTORS,COMPANIES.OTHER_CONTACTS AS OTHER_CONTACTS,

    COMPANIES.DESCRIPTION AS DESCRIPTION,COMPANIES.ACTIVE_FLAG AS

    ACTIVE_FLAG,COMPANIES.BE_CREATED_DATE AS BE_CREATED_DATE,

    COMPANIES.LAST_UPDATED_DATE AS LAST_UPDATED_DATE,

    COMPANIES.PUBLIC_FLAG AS PUBLIC_FLAG,COMPANIES.COMPANY_TYPE

    AS COMPANY_TYPE,COMPANIES.IS_OUTER_FLAG AS IS_OUTER_FLAG,

    COMPANIES.AGENCY_DISTRICT_ID AS AGENCY_DISTRICT_ID,

    COMPANIES.SCOPE AS SCOPE

    FROM Z_COMPANIES COMPANIES,CORPORATION CORPORATION,

    COMPANY_PASSWORD COMPANY_PASSWORD

    WHERE COMPANIES.COMPANY_ID=14560403

    AND

    COMPANIES.REGISTER_COMPANY_CODE=UPPER(CORPORATION.DWZZJGDM)

    AND CORPORATION.CID=COMPANY_PASSWORD.CID

建議去掉UPPER,改爲COMPANIES.REGISTER_COMPANY_CODE=CORPORATION.DWZZJGDM

 

:

where to_char(time,'yyyymm')='200501'

建議儘可能不要使用DATE數據類型,因爲一使用to_char函數作用就不用索引.

對於上述語句可酌情改爲where time>=to_date('200501','yyyymm') and time<to_date('200502','yyyymm')

 

:

select count(*) as record_count from

       (SELECT POSITION.SALARY1 ||'-'|| POSITION.SALARY2 AS SALARY,

              POSITION.YZSLCD_ID_2 AS YZSLCD_ID2,

              POSITION.MIN_AGE ||'-'|| POSITION.MAX_AGE AS AGE,

              POSITION.POSITION_ID AS POSITION_ID,

              POSITION.NAME as POSITION_NAME,POSITION.WHCD_ID AS WHCD_NAME,

              POSITION.TOTAL_NUMBER AS TOTAL_NUMBER,

              POSITION.DIC_CITY_AND_AREA_ID_1 AS DIC_CITY_AND_AREA_NAME_1,

              DIC_UNIT_PROPERTY.DWXZ_NAME as DWXZ_NAME,

              POSITION.IS_ZJ AS IS_ZJ,POSITION.ZJ_ZZJGDM AS ZJ_ZZJGDM,

              to_char(POSITION.be_created_date,'YY-MM-DD') as BE_CREATED_DATE,

              POSITION.IS_ZJS 

              FROM  Z_POSITIONS POSITION,DIC_UNIT_PROPERTY 

       WHERE (DIC_UNIT_PROPERTY.DWXZ_ID = POSITION.DWXZ_ID)

              AND to_char(POSITION.BE_CREATED_DATE,'yyyymmdd')<=to_char(sysdate,'yyyymmdd')

             AND (SUBSTR(position.DIC_STATION_POSITION_ID,1,4)='0002') AND (POSITION.HISTORY_FLAG='N')

             AND (POSITION.ACTIVE_FLAG='Y') AND POSITION.END_DATE >= trunc(sysdate) AND POSITION.FULL_FLAG>0 );

建議將條件(SUBSTR(position.DIC_STATION_POSITION_ID,1,4)='0002')

改爲position.DIC_STATION_POSITION_ID like '0002%')

 

 

3. 避免系統隱含的數據類型轉換

:

SELECT cid,pid

    FROM COG_ROSTER_ANNUAL_W

    WHERE cid=200008010754371

cidNUMBER數據類型,請使用cid=200008010754371,cidCHAR數據類型,請使用cid='200008010754371',

否則系統將自動進行數據類型轉換,導致全表掃描而不使用索引

 

 

4. 儘可能減少不必要的語句

:部分程序

select count(*) from icq_payment where pid=:a1;

select * from icq_payment where pid=:a1;

 

建議:可以直接執行後一條語句,輔以查詢不到的意外處理.

 

 

5. 儘量用簡單的語句,及減少不必要的判斷條件

:

select max(dh)

    from mail_record group by bh having bh='2005020666';

儘量避免使用GROUP BY,HAVING等複雜子句,可使用下列語句達到同樣效果:

select max(dh)

    from mail_record where bh='2005020666';

 

:

Select count(*)

    From ICQ_PAYMENT

    Where (QSNY <= ZZNY or ZZNY is null)

    and pid='200008029162760'

該語句爲查詢社保個人繳費信息,點擊率非常高,

而實際上QSNY永遠=ZZNY,所以條件(QSNY <= ZZNY or ZZNY is null)沒有意義,白白浪費CPU運算

 

6. 中文檢索

對於中文查詢,如姓名,單位名稱,其他各類中文名稱等,若業務需求允許,儘可能要求漢字必須從頭輸入.

如將條件position.name LIKE '%駕駛員%',改成position.name LIKE '駕駛員%',則可使用position表上name字段的索引,

若兩頭模糊查詢,則只能全表掃描.將損失很多性能。

 

7. 特殊情況下,增加註釋,強制使用索引

有些情況下系統選擇的執行計劃會不正確,如會選擇使用全表掃描,而不使用索引,但經測試發現實際上使用索引效率高得多,

這時可強制使用索引:

:

select count(*)

    from mail_record,dic_status 

    where mail_record.zt = dic_status.status_id

    and mail_record.scbj =0

    and mail_record.zt ='0000';

測試發現,雖然mail_record上的zt字段有索引,但系統未使用,而進行全表掃描,

建議改爲

select /*+ INDEX(A,IDX_MAIL_RECORD_ZT) */ count(*)

    from mail_record A,dic_status B

    where A.zt = B.status_id

    and A.scbj =0

    and A.zt ='0000';

select後面增加的hint (/*+ INDEX(A,IDX_MAIL_RECORD_ZT) */) 的意思是

強制使用別名爲Amail_record表上的索引IDX_MAIL_RECORD_ZT.(在此種情況下一定要使用表的別名)

強制使用索引一定要經過測試.在沒有把握或不能確定的情況下,儘可能不要使用hint,尤其是rule hint,/*+ RULE */,   而讓系統自己選擇執行計劃,因爲在絕大部分情況下,系統選擇執行計劃還是相當不錯的.   當確定要使用某種hint,一定要經過測試.

 

補充資料:

在維護查詢的性能時,我覺得選擇得體的優化方法應該是個要注意的問題。oracle在早期的版本中最新運用的是基於規則優化器(RBO),從ORACLE 7開始引入了基於開銷(成本)優化器(CBO),從此,也就有了analyze工具,它爲表或索引生成統計和估計資料。
在INIT.ORA中可以爲數據庫設置確省的優化設置:optimizer_mode,在會話中可以動態的改變優化器模式,如set session set optimizer_goal.。oracle提供了四種優化模式:
(1)。 rule:選擇oracle使用基於規則的優化。如果我們試圖使用RBO對SQL語句進行優化時,可以設置爲RULE。請注意,RBO經常不能選擇最優的執行計劃,因爲它不能夠選擇最佳的索引
(2)。 CHOOSE:這是ORACLE的默認方式,它會根據是否能夠找到統計數字來決定使用那種優化方式,如果沒有統計數字的話,它會使用RULE;如果存在統計數字的話,它會根據是否存在索引等信息選擇使用FIRST_ROW還是ALL_ROWS。當統計資料不完整時,比如說有的表有,另外一些沒有,那麼CHOOSE會使用基於成本的優化器,並且在運行是對另外的表做統計和估計,從而影響了效率,甚至導致嚴重的效率下降問題。
(3)。 FIRST_ROW:使用CBO,它能快速返回最初的幾行,因爲它通常使用完全索引掃描,從而會造成總體效率降低或者消耗更多的系統資源。往往適合於一些ONLINE系統,因爲人們總是希望儘快看到反映。
(4)。 ALL_ROWS:它也是用CBO,但它的不表示是總體反應時間縮短,因爲它通常使用並行全表掃描,而不使用完全索引掃描

另外,可以使用HINTS,在部分語句級指定優化方式

 

8.在確定字段類型時,應準確選擇

  儘可能少用date類型;

  若放數字,應使用number類型,而不要使用char類型,避免混入異常字符;

   -字段的長度儘可能估算準確,避免過長,導致空間浪費;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章