1、數據庫級的優化sql
1. nccm_chargedetail 表分區 1499萬 半年數據量 (解決百萬級,千萬級數據量)
partition by list (BURYEAR)
(
partition P_2013 values ('2013')
tablespace T_2013
pctfree 10
initrans 1
maxtrans 255
storage (
initial 3114M
next 1M
minextents 1
maxextents unlimited
)
);
2. 索引 (index)
假設表中有100000行,而sql要讀取表中20%的行,也就是20000;再作個假設,若是行大小
約80字節,那麼塊大小爲8kb的塊則大約100行,這說明表大約1000個塊。那麼經過索引讀取
的話, 大約20000個TABLE ACCESS BY ROWID
操做來執行查詢,那麼須要處理200000個塊,但整個表才1000個塊。
在這種狀況下,全表掃描要比用索引高效。
索引使用規則:一般對於小表,Oracle建議經過全表掃描進行數據訪問,對於大表則應該
經過索引以加快數據查詢,固然若是查詢要求返回表中大部分或者所有數據,那麼全表掃
描可能仍然是最好的選擇。
像查詢nccm_clinicsub 門診報銷表中某個家庭的全部報銷單據,有什麼理由不用索引呢 ?
select * from nccm_clinicsub h where h.famid='4115252521010313' and h.buryear='2013';
索引須要空間來存儲,也須要按期維護,
每當有記錄在表中增減或索引列被修改時, 索引自己也會被修改.
這意味着每條記錄的INSERT , DELETE , UPDATE將爲此多付出4 , 5 次的磁盤I/O .
由於索引須要額外的存儲空間和處理,那些沒必要要的索引反而會使查詢反應時間變慢。數據庫
3. 鏈接池 (Connection Pool機制)
鏈接會話的三種狀態 active inactive killed
合理的配置鏈接池: 最小鏈接數、最大鏈接數、閒置鏈接數、回收鏈接時間
4. 視圖 (view) nccm_mtp
視圖是基於一個表或多個表或視圖的邏輯表,自己不包含數據,經過它能夠對
表裏面的數據進行查詢和修改。視圖基於的表稱爲基表。視圖是存儲在數據字
典裏的一條select語句。 經過建立視圖能夠提取數據的邏輯上的集合或組合。
視圖的優勢:
① 對數據庫的訪問,由於視圖能夠有選擇性的選取數據庫裏的一部分。
② 用戶經過簡單的查詢能夠從複雜查詢中獲得結果。
③ 維護數據的獨立性,試圖可從多個表檢索數據。
④ 對於相同的數據可產生不一樣的視圖。
dic_code_medical dic_code_treat dic_code_ops
create or replace view nccm_mtp as sql;
5. 臨時表
create global temporary table 臨時表名 on commit preserve|delete rows ;
用preserve時就是SESSION級的臨時表,用delete就是TRANSACTION級的臨時表;
① 循環SQL:系統中有不少相似的sql循環執行,效率很低
② 多表關聯: 利用臨時表簡化有太多表關聯的複雜SQL
③ 若是某個數據集會重複屢次使用的狀況下建議使用臨時表
④ 臨時表做爲複雜查詢條件的中間結果用於主查詢
nccm_pro_prov_report_03oracle
6. 控制碎片
碎片(fragmentation)是對一組非鄰接的數據庫對象的描述。碎片意味着在執行數據庫
的功能時要耗費額外的資源(磁盤I/O,磁盤驅動的循環延遲,動態擴展,連接的塊等)
,並浪費大量磁盤空間。當兩個或多個數據對象在相同的表空間中,會發生區間交叉。
在動態增加中,對象的區間之間再也不相互鄰接。爲了消除區間交叉將靜態的或只有小增
長的表放置在一個表空間中,而把動態增加的對象分別放在各自的表空間中。
在create table、、create index、create tablespace、create cluster時,
在storage(指定對象的存儲參數)子句中的參數的合理設置,能夠減小碎片的產生。
① 字典表、變更少的表 用表空間1;
②天天都動態增加的表用 表空間二、三、4等;
③storage參數的意義;
2、sql級優化
1. oralce優化器
執行計劃: 在執行sql語句時,Oracle須要執行不少步驟。在每一步中,Oracle或者從
數據庫中讀取數據,或者爲用戶提交sql語句準備數據。這些Oracle在執行sql語句時使用
的步驟的集合叫作執行計劃。
oracle優化器:在執行sql語句時,oracle優化器都要對sql語句進行解析,獲得一個執行計劃。
由於解析操做比較浪費系統資源,致使系統性能降低。因此解析完sql語句後,都要將解析獲得
的執行計劃保存在內存中。若是再次執行該sql,就不須要解析了,直接從內存中獲取其執行計劃。
因此再次提醒儘可能減小訪問數據庫的次數以及sql語句的執行次數,不要在客戶機器上開開pl/sql
不關,一直佔用資源。更甚着有用for update鎖表的(致使程序短期掛掉)。查看錶的時候不要用
編輯表,而是用查看錶。
Hints(提示):基於代價的優化器是很聰明的,在絕大多數狀況下它會選擇正確的優化器,減輕
了DBA的負擔。但有時它也聰明反被聰明誤,選擇了不好的執行計劃,使某個語句的執行變得奇
慢無比。此時就須要DBA進行人爲的干預,告訴優化器使用咱們指定的存取路徑或鏈接類型生成
執行計劃,從而使語句高效的運行。
例如,若是咱們認爲對於一個特定的語句,執行全表掃描要比執行索引掃描更有效,則咱們就
能夠指示優化器使用全表掃描。在Oracle中,是經過爲語句添加 Hints(提示)來實現干預優化
器優化的目的。
建立執行計劃表:sqlplus nccm/nccm@nccm
sql> @D:\app\Administrator\product\11.1.0\db_2\RDBMS\ADMIN\utlxplan.sql
查看執行計劃表的結構:desc plan_table;
id 步驟編號 operation 所執行內部操做名稱 optimizer 優化器當前的模式 cost 操做成本
cardinality 訪問行數 bytes 訪問的字節數
查看執行計劃: explain plan for select * from nccm_hossubsidy;
查看執行計劃表的數據: select * from plan_table;
查看格式化的數據:
select lpad('', 2 * (level - 1)) || operation || '' || options || '' ||
object_name || '' || decode(id, 0, 'Cost=' || position) "Query Plan"
from plan_table connect by prior id = parent_id;
刪除表中的數據:delete from plan_table;
最優的查詢plan_table方式:select * from table(DBMS_XPLAN.display);
最最優的查詢方式:用pl/sql的F5
2. FROM/WHERE子句中的鏈接順序
經測試只在基於規則的優化器中有效;而oracle默認的是ebo模式;
查看當前優化器模式:
select name,value from v$parameter where name ='optimizer_mode';
alter system set optimizer_mode=Rule scope=spfile;
關閉實例 卸載數據庫: shutdown或者shut immediate;
開啓實例 打開數據庫: connect /as sysdba; startup;
Rule: 不用多說,即走基於規則的方式。
Choolse: 這是咱們應觀注的,默認的狀況下Oracle用的即是這種方式。指的是當一個
表或或索引有統計信息,則走CBO的方式,若是表或索引沒統計信息,表又不是特別的小,並且
相應的列有索引時,那麼就走索引,走RBO的方式。
First Rows: 它與Choose方式是相似的,所不一樣的是當一個表有統計信息時,它將是以最快
的方式返回查詢的最早的幾行,從整體上減小了響應時間。
All Rows: 也就是咱們所說的Cost的方式,當一個表有統計信息時,它將以最快的方式返
回表的全部的行,從整體上提升查詢的吞吐量。沒有統計信息則走基於規則的方式。
select * from nccm_hossubsidy h ,nccm_joinperson j where h.personid=j.personid;
select * from nccm_joinperson j ,nccm_hossubsidy h where h.personid=j.personid;
select * from nccm_clinicsub c where c.famid='4115250528010234'
and c.birthday='19000101';
select * from nccm_clinicsub c where c.birthday='19000101' and
c.famid='4115250528010234' ;
自從oracle添加優化器功能後,已經沒有效果了; 雖然加載條件與表的順序依然是從右到左。
3. 索引的恰當使用
where子句中對索引字段計算運用函數、類型轉換等會致使索引的失效!
select * from nccm_clinicsub c where substr(c.famid,1,16)='4115250528010234'
and c.birthday='19000101';
select * from nccm_clinicsub c where c.famid||'01'='411525052801023401'
and c.birthday='19000101';
4. 在程序中儘可能多使用COMMIT
nccm_savePayfeeinfo 農合繳費過程 沒有及時的commit
5. 見過最奇葩的sql語句:
select c,name,c.orgcode,c.diagdate from nccm_clinicsub c
where c.famid='4115250528010234' and c.buryear='2013';
循環遍歷:
select p.pointegername from nccm_pointegerorg p where p.pointegercode=orgcode;
app
6. in、exists、group by的正確使用
group by的having和where
select orgcode, h.orglevel, sum(h.factsub)
from nccm_hossubsidy h
where h.orglevel > 3
group by h.orgcode, h.orglevel
select orgcode, h.orglevel, sum(h.factsub)
from nccm_hossubsidy h
group by h.orgcode, h.orglevel
having h.orglevel > 3
經測試not in/exists 無效
select *
from nccm_hossubsidy h
where h.villcode in (select t.villcode
from nccm_hossubsidy t
where t.villcode = '4115252521');
select *
from nccm_hossubsidy h
where exists (select 1
from nccm_hossubsidy t
where t.villcode = h.villcode
and t.villcode = '4115252521');
select *
from nccm_chargedetail c
where c.billcode not in
(select h.billcode
from nccm_hossubsidy h
where h.billcode = 'Z0000000000000000011');函數
select *
from nccm_chargedetail c
where not exists (select 1
from nccm_hossubsidy h
where h.billcode = c.billcode
and h.billcode = 'Z0000000000000000011');
爲何exists與in的效果同樣呢???
在oracle 9i中,默認提供是基於選擇的優化器,即當有分析數據時,採用基於成本的優化方式,
沒有則仍採用基於規則的查詢方式,這樣優化模式下基本等同於基於規則或者基於成本。在10g之
後的版本,默認都是以基於成本的方式進行,這時候,oracle會先找出可能的執行方式,而後計算
出每一個執行計劃的成本,再選擇以較低成本的方式進行計算,這樣子在對in和exists的分析中,這
兩種寫法會相互轉換,那個統計的成本信息低則會選擇那種方式。固然因爲oracle的成本信息並不
是全量統計得出來的結果,也會有必定的偏差,再統計信息是須要人工(或定時)去執行統計的,
若是操做大量數據後,沒有進行統計,誤差也會很大。
批量插入數據優化:
常規的插入方法:
循環loop 10000:
insert into table (a,b,c,d);
end;
批量插入的方法:
循環loop 100:
v_sql:='insert into table select a,b,c,d from dual';
循環loop 100:
v_sql:=v_sql||'union all select a,b,c,d from dual';
end;
execute immediate v_sql;
end;
批量插入僅僅完成100次插入,效率要遠遠高於10000次的常規插入。
儘可能不要使用‘*’以及用select max(clicode) from nccm_clinicsub c
oop