11 SQL調優概述

11.3調優程序/減輕負載

如果期望減輕數據庫服務器整體的CPU或者I/O負載,可通過以下步驟確定資源密集型的SQL語句:

1.選擇在應用程序的處理高峯期檢測。

2.在以上週期內,收集操作系統及Oracle統計信息。需要收集的Oracle統計信息至少包括文件的I/O(通過視圖V$FILESTAT),系統統計信息(V$SYSSTAT),以及SQL統計信息(V$SQLAREA , V$SQL or V$SQLSTATS , V$SQLTEXT , V$SQL_PLAN , and V$SQL_PLAN_STATISTICS )。

3.通過第二步收集的統計信息來確定使用最多資源的SQL語句,可以通過對V$SQL中的數據排序來斷定資源的使用情況。一般關注的資源是:

  • Buffer gets (V$SQL .BUFFER_GETS , 較耗CPU的語句)

  • Disk reads (V$SQL .DISK_READS , 較耗I/O的語句)

  • Sorts (V$SQL .SORTS , 大量排序)

較注重CPU的優化,可以首先從buffer gets值較高的語句入手,否則,對於I/O來說,從DISK_READS較高的SQL語句開始。

11.5.1驗證優化器統計信息

查詢優化器使用從表、索引收集的統計信息來決定最優的執行計劃。如果統計信息未收集或者存儲在數據庫中數據庫的統計信息已不具代表性,則優化沒有足夠的統計信息來生成最優的執行計劃。

1.最好爲所有表收集統計信息,特別是SQL語句中表連接涉及的表需要收集統計信息。

2.表中的實際行數(row count)與DBA_TABLES.NUM_ROWS的值做比較,是一個檢驗數據字典的統計信息是否過時的好方法。

11.5.3索引失效

1.不要在SQL謂詞及條件子句中使用SQL函數,定義了基於函數的索引列上使用除外

2.避免在條件字句中的列上使用類型轉換。

例如

WHERE TO_NUMBER (SUBSTR(a.order_no, INSTR(b.order_no, '.') - 1))=

TO_NUMBER (SUBSTR(a.order_no, INSTR(b.order_no, '.') - 1))

包括隱式轉換,例如

VARCHAR2類型列USERNAME,條件使用了NUMBER值,WHERE USERNAME=1200

正確方式:WHERE USERNAME='1200'

11.5.4EXISTS和IN

例子:

表employees,有唯一索引employee_id字段,索引字段 department_id,數據量27000

表orders,索引字段customer_id,數據10000條

employees.employee_id與orders.sales_rep_id關聯

子查詢有索引列過濾條件,且返回結果較少時,外層條件字句中適合使用IN

例如:

SELECT e.employee_id, e.first_name, e.last_name, e.salary

FROM employees e

WHERE e.employee_id IN (SELECT o.sales_rep_id

FROM orders o WHERE o.customer_id = 144);

要優於

SELECT e.employee_id, e.first_name, e.last_name, e.salary

FROM employees e

WHERE EXISTS (SELECT 1 FROM orders o

WHERE e.employee_id = o.sales_rep_id

AND o.customer_id = 144);

而子查詢無索引過濾條件,或者返回數據較大時,外層條件字句中適合使用EXISTS

例如:

SELECT e.employee_id, e.first_name, e.last_name, e.salary

FROM employees e

WHERE e.department_id = 80

AND e.job_id = 'SA_REP'

AND EXISTS (SELECT 1

FROM orders o

WHERE e.employee_id = o.sales_rep_id);

優於

SELECT e.employee_id, e.first_name, e.last_name, e.department_id, e.salary

FROM employees e

WHERE e.department_id = 80

AND e.job_id = 'SA_REP'

AND e.employee_id IN (SELECT o.sales_rep_id FROM orders o);

當然,如果在department_id、job_id字段上建立聯合索引,效率將進一步提升。

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