1 通過rowid訪問表--索引
你可以採用基於rowid的訪問方式情況,提高訪問表的效率, , rowid包含了表中記錄的物理位置資訊..oracle採用索引(index)實現了資料和存放資料的物理位置(rowid)之間的聯絡. 通常索引提供了快速訪問rowid的方法,因此那些基於索引列的查詢就可以得到效能上的提高.
2 共享sql語句--相同的sql放入快取
3 選擇最有效率的表名順序(只在基於規則的優化器中有效) 最右邊的表作為基礎表(記錄最少,效率最高)
oracle的解析器按照從右到左的順序處理from子句中的表名,因此from子句中寫在最後的表(基礎表 driving table)將被最先處理. 在from子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表.當oracle處理多個表時, 會運用排序及合併的方式連線它們.首先,掃瞄第乙個表(from子句中最後的那個表)並對記錄進行派序,然後掃瞄第二個表(from子句中最後第二個表),最後將所有從第二個表中檢索出的記錄與第乙個表中合適記錄進行合併.
例如:表 tab1 16,384 條記錄
表 tab2 1 條記錄
選擇tab2作為基礎表 (最好的方法)
select count(*) from tab1,tab2 執行時間0.96秒
選擇tab2作為基礎表 (不佳的方法)
select count(*) from tab2,tab1 執行時間26.09秒
如果有3個以上的表連線查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表.
例如:emp表描述了location表和category表的交集.
select *
from location l ,
category c,
emp e
where e.emp_no between 1000 and 2000
and e.cat_no = c.cat_no
and e.locn = l.locn
將比下列sql更有效率
select *
from emp e ,
location l ,
category c
where e.cat_no = c.cat_no
and e.locn = l.locn
and e.emp_no between 1000 and 2000
4. where子句中的連線順序.
oracle採用自下而上的順序解析where子句,根據這個原理,表之間的連線必須寫在其他where條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在where子句的末尾.
5 用explain plan 分析sql語句
explain plan 是乙個很好的分析sql語句的工具,它甚至可以在不執行sql的情況下分析語句. 通過分析,我們就可以知道oracle是怎麼樣連線表,使用什麼方式掃瞄表(索引掃瞄或全表掃瞄)以及使用到的索引名稱.
6.分頁sql
一般的分頁sql如下所示:
sql1:select * from (select t.*,rownum rn from *** t)where rn>0 and rn <10;
sql2:select * from (select t.*,rownum rn from *** t where rownum <10)where rn>0;
乍看一下沒什麼區別,實際上區別很大...125萬條資料測試,
sql1平均需要1.25秒(咋這麼準呢? )
sql2平均需要... 0.07秒
原因在於,子查詢中,sql2排除了10以外的所有資料
當然了,如果查詢最後10條,那效率是一樣的
7.多exists,少in
exists只檢查存在性,效能比in強很多,有些朋友不會用exists,就舉個例子
例,想要得到有**號碼的人的基本資訊,table2有冗餘資訊
select * from table1;--(id,name,age)
select * from table2;--(id,phone)
in:
select * from table1 t1 where t1.id in (select t2.id from table2 t2 where t1.id=t2.id);
exists:
select * from table1 t1 where exists (select 1 from table2 t2 where t1.id=t2.id);
(補充內容)用in的朋友注意了,當引數超過1000個,資料庫就掛了。(oracle 10g資料庫)
8.少用*
很多朋友很喜歡用*,比如:select * from ***;
一般來說,並不需要所有的資料,只需要一些,有的僅僅需要1個2個,
拿5w的資料量,10個屬性來測試:
(這裡的時間指的是pl/sql developer顯示所有資料的時間)
使用select * from ***;平均需要20秒,
使用select column1,column2 from ***;平均需要12秒
(我的機子不是很好。。。)
對於開發來說,這一條是個災難,知道是一回事,做就是另一回事了
9 一些查詢往往會聯接十幾張甚至幾十張表
應用設計的時候對這樣的查詢要很慎重。如果**很大,十幾張表做聯接,肯定不會有好的效能。如果應用是支援資料分析系統,那可能還好。如果應用是乙個oltp系統(要求很快返回結果),這樣的設計失敗的風險可能會很大。有時候可能需要降低資料庫正規化級別,多儲存一些冗餘資料列,以減少**聯接的數量
10 慎用distinct關鍵字
distinct在查詢乙個字段或者很少欄位的情況下使用,會避免重複資料的出現,給查詢帶來優化效果。
但是查詢字段很多的情況下使用,則會大大降低查詢效率。因為當查詢很多欄位時,如果使用distinct,資料庫引擎就會對資料進行比較,過濾掉重複資料,然而這個比較,過濾的過程則會毫不客氣的占用系統資源,cpu時間。
11 like
去掉前置百分號。like語句會因為前置百分號而無法使用索引
12 使用儲存過程
可以考慮使用儲存過程封裝那些複雜的sql語句或商業邏輯,這樣做有幾個好處。
一是儲存過程的執行計畫可以被快取在記憶體中較長時間,減少了重新編譯的時間。
二是儲存過程減少了客戶端和伺服器的繁複互動。
三是如果程式發布後需要做某些改變你可以直接修改儲存過程而不用修改程式,避免需要重新安裝部署程式。
13 複雜sql
對於非常複雜的sql(特別是有多層巢狀,帶子句或相關查詢的),應該先考慮是否設計不當引起的。對於一些複雜sql可以考慮使用程式實現。
14 避免in子句
使用in 或 not in子句時,特別是當子句中有多個值時,且查詢資料表資料較多時,速度會明顯下降。可以採用連線查詢或外連線查詢來提高效能。
15 批量插入資料 insert into select 提高效能
16 sys_guid() ,sysdate,序列sequence
17 上億資料量資料庫優化
避免全表掃瞄,使用儲存過程,建立臨時表,其他一些查詢條件調優不贅述
Oracle中SQL效能優化(持續更新)
decode函式相當於case when 但是decode從效率上來講是強於case when的,但是從個人使用的角度來說case when的使用可以更加多樣化,這一點強於decode,兩者的選擇還是從現實中抉擇。刪除資料的角度來說,可以使用 truncate和delete和drop,從效率來說tr...
SQL 優化筆記,持續更新
sql var x number sql exec x 90 pl sql procedure successfully completed.sql set autot exp usage set autot race exp lain stat istics sql set autot trace...
mysql優化積累 持續更新中
大表資料查詢 主從複製 讀寫分離 垂直拆分 水平切分 資料庫設計和查詢原則 盡量設定主鍵 推薦使用自增id,不要使用uuid 字段定義為not null而不是null 密碼雜湊,鹽,使用者身份證號等固定長度的字串應該使用char而不是varchar來儲存,這樣可以節省空間且提高檢索效率。避免犯如下s...