1.表名順序優化
(1) 基礎表放下面,當兩表進行關聯時數據量少的表的表名放右邊
表或視圖:
Student_info (30000條數據)
Description_info (30條數據)
select *
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
與
select *
from student_info si--學生信息表
,description_info di
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
以student_info做爲基礎表,你會發現運行的速度會有很大的差距。
(2) 當出現多個表時,關聯表被稱之爲交叉表,交叉表做爲基礎表
select *
from description_info di
,description_info di2
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and si.school_id = di.lookup_code(+)
and di.lookup_type(+) = 'SCHOOL_ID'
與
select *
from student_info si--學生信息表
,description_info di
,description_info di2
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and si.school_id = di.lookup_code(+)
and di.lookup_type(+) = 'SCHOOL_ID'
以student_info做爲基礎表,你會發現運行的速度會有很大的差距,
當基礎表放在後面,這樣的執行速度會明顯快不少。java
2.where執行順序
where執行會從至下往上執行
select *
from student_info si --學生信息表
where si.school_id=10 --學院ID
and si.system_id=100--系ID
擺放where子句時,把能過濾大量數據的條件放在最下邊mysql
3. is null 和is not null
當要過濾列爲空數據或不爲空的數據時使用
select *
from student_info si --學生信息表
where si.school_id is null(當前列中的null爲少數時用is not null,不然is null)sql
4.使用表別名
當查詢時出現多個表時,查詢時加上別名,
避免出現減小解析的時間字段歧義引發的語法錯誤。數據庫
5. where執行速度比having快
儘量的使用where代替having
select from student_info si
group by si.student_id
having si.system_id!=100
and si.school_id!=10
(select from student_info si
wehre si.system_id!=100
and si.school_id!=10
group by si.student_id)
6. * 號引發的執行效率
儘可能減小使用select * 來進行查詢,當你查詢使用*,
數據庫會進行解析並將*轉換爲所有列。oracle
2、替代優化
一、用>=替代>
select ui.user_name
from user_info ui--員工信息表
where ui.student_id>=10
與
select ui.user_name
from user_info ui--員工信息表
where ui.student_id>9
執行時>=會比>執行得要快
二、用UNION替換OR (適用於索引列)
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
union
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=2
上面語句可有效避免全表查詢
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
or ui.student_id=2
若是堅持要用OR, 能夠把返回記錄最少的索引列寫在最前面
三、用in 代替or
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
or ui.student_id=20
or ui.student_id=30
改爲
select ui.user_name
from user_info ui--員工信息表
where ui.student_id in (10,20,30)
執行會更有效率
四、 Union All 與Union
Union All重複輸出兩個結果集合中相同記錄
若是兩個並集中數據都不同.那麼使用Union All 與Union是沒有區別的,
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
union All
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=2
與
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=10
union
select ui.user_name
from user_info ui--員工信息表
where ui.student_id=2
但Union All會比Union要執行得快函數
五、分離表和索引
老是將你的表和索引創建在另外的表空間內
決不要將這些對象存放到SYSTEM表空間裏性能
3、一些優化技巧測試
一、計算表的記錄數時優化
select count(si.student_id)
from Student_info si(student_id爲索引)
與
select count(*) from Student_info si
執行時.上面的語句明顯會比下面沒有用索引統計的語句要快ui
2.使用函數提升SQL執行速度
當出現複雜的查詢sql語名,能夠考慮使用函數來提升速度
查詢學生信息並查詢學生(李明)我的信息與的數學成績排名
如
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.description = '李明'
並且咱們將上面order_num排名寫成一個fuction時
create or replace package body order_num_pkg is
function order_num(p_student_id number) return_number is
v_return_number number;
begin
select res.order_num --排名
into v_return_number
from result res
where res.student_id = di.student_id
order by result_math;
return v_return_number;
exception
when others then
null;
return null;
end;
end order_num_pkg;
執行
select di.description student_name
,order_num_pkg.order_num(di.student_id) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.description = '李明'
執行查詢時的速度也會有所提升
3.減小訪問數據庫的次數
執行次數的減小(當要查詢出student_id=100的學生和student_id=20的學生信息時)
select address_id
from student_info si --學生信息表
where si.student_id=100
與
select address_id
from student_info si --學生信息表
where si.student_id=20
都進行查詢.這樣的效率是很低的
而進行
(
select si.address_id,si2.address_id
from student_info si --學生信息表
,student_info si2
where si.student_id=100
and si2.student_id=20
與
select decode(si.student_id,100,address_id)
,decode(si.student_id,20,address_id)
from student_info si
)
執行速度是提升了,但可讀性反而差了..
因此這種寫法我的並不太推薦
四、用Exists(Not Exists)代替In(Not In)
在執行當中使用Exists或者Not Exists能夠高效的進行查詢
五、Exists取代Distinct取惟一值的
取出關聯表部門對員工時,這時取出員工部門時,出現多條..
select distinct di.dept_name
from departments_info di --部門表
,user_info ui --員工信息表
where ui.dept_no = di.dept_no
能夠修改爲
select di.dept_name
from departments_info di --部門表
where exists (select 'X'
from user_info ui --員工信息表
where di.dept_no = ui.dept_no)
六、用錶鏈接代替Exists
經過表的關聯來代替exists會使執行更有效率
select ui.user_name
from user_info ui--員工信息表
where exists (select 'x '
from departments_info di--部門表
where di.dept_no = ui.dept_no
and ui.dept_cat = 'IT');
執行是比較快,但還可使用表的鏈接取得更快的查詢效率
select ui.user_name
from departments_info di
,user_info ui --員工信息表
where ui.dept_no = di.dept_no
and ui.department_type_code = 'IT'
代碼是經測試並進行優化所寫,
以上只例子,具體使用仍是要針對各個不一樣的具體的業務使用用Exists(Not Exists)代替In(Not In)
4、索引篇
一、運算致使的索引失效
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and si.student_id+0=100/*student_id索引將失效*/
二、類型轉換致使的索引失效
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id='100'
student_id爲number類型的索引,當執行下列語句,
oracle會自動轉換成
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id=to_number('100')
所幸,只是解析並轉換類型,並無導到失效,
但要是寫成下面,將會使用其失效
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and to_char(di.student_id)='100'
三、在索引列上進行計算引發的問題
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id-2=10
在索引列中進行運算,將會不使用索引而使用全表掃描
而將
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.student_id=10+2
將會獲得高效的運行速度
四、 Is not null引發的問題(student_id爲索引)
不要把存在空值的列作爲索引,不然沒法使用索引
select ui.user_name
from user_info ui--員工信息表
where ui.student_id is not null--索引失效
select ui.user_name
from user_info ui--員工信息表
where ui.student_id>=-1--索引有效
五、Order by致使索引失效(student_id爲索引)
select ui.user_name
from user_info ui--員工信息表
group by ui.student_id
而使用
select ui.user_name
from user_info ui--員工信息表
where ui.student_id>=-1
將使其有效,
在order by中只存在兩種條件下可使用索引
(ORDER BY中全部的列必須包含在相同的索引中並保持在索引中的排列順序
ORDER BY中全部的列必須定義爲非空. )
六、自動選擇索引
若是表中有兩個以上(包括兩個)索引,其中有一個惟一性索引,而其餘是非惟一性.
在這種狀況下,ORACLE將使用惟一性索引而徹底忽略非惟一性索引.
七、 !=致使索引失效
select ui.user_name
from user_info ui--員工信息表
where ui.student_id!=0
在Where中使用!=將會把索引失效
八、%致使的索引失效
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.look_code Like '%12'/*look_code爲索引,索引將失效*/
而
select di.description student_name
,(select res.order_num--排名
from result res
where res.student_id = di.student_id
order by result_math) order_num
from description_info di
,student_info si --學生信息表
where si.student_id = di.lookup_code(+)
and di.lookup_type(+) = 'STUDENT_ID'
and di.look_code Like '12%'/*索引有效*/
以上只例子,具體仍是要針對各個不一樣的具體的業務使用
5、oracle 中的not Exists與Not in的性能巨大差別
Not Exists與Not in的做用一樣是排除數據,在oracle 中使用not in並不象mysql中的執行那麼快,如(
select jt1.doc_num --單據號碼
,oalc.description school_name --學校名稱
,oalc2.description system_name --系名稱
,oalc.description class_name --班級名稱
from java_table1 jt1
,java_table_description oalc
,java_table_description oalc2
,java_table_description oalc3
where oalc.lookup_type(+) = 'JAVA_SCHOOL_NAME'
and jt1.school_id = oalc.lookup_code(+)
and oalc2.lookup_type(+) = 'JAVA_SYSTEM_NAME'
and jt1.system_id = oalc2.lookup_code(+)
and oalc3.lookup_type(+) = 'JAVA_CLASS_NAME'
and jt1.class_id = oalc3.lookup_code(+)
and not exists
(select jt2.header_id
from java_table2 jt2 jt1.header_id = jt2.header_id))
與
select jt1.doc_num --單據號碼
,oalc.description school_name --學校名稱
,oalc2.description system_name --系名稱
,oalc.description class_name --班級名稱
from java_table1 jt1
,java_table_description oalc
,java_table_description oalc2
,java_table_description oalc3
where oalc.lookup_type(+) = 'JAVA_SCHOOL_NAME'
and jt1.school_id = oalc.lookup_code(+)
and oalc2.lookup_type(+) = 'JAVA_SYSTEM_NAME'
and jt1.system_id = oalc2.lookup_code(+)
and oalc3.lookup_type(+) = 'JAVA_CLASS_NAME'
and jt1.class_id = oalc3.lookup_code(+)
and jt1.header_id not in (select jt2.header_id from java_table2 jt2)
當jt2表中的數據比較大時,就會出現巨大的差別,以上只能是個人我的理解與測試結果(java_table1 視圖測試
數據量爲36749,java_table2 爲300條)