SQL优化实用方法
SQL優(yōu)化:避免索引失效
1、不使用NULL
任何在where子句中使用is null或is not null的語句優(yōu)化器是不允許使用索引的。因為只有該字段中有null值,即使創(chuàng)建了索引其實也
是沒有用的,所以創(chuàng)建索引應(yīng)該在有值的字段上創(chuàng)建;
2、like的使用
使用該sql語句將不會使用索引:select * from employee where last_name like ‘%cliton%';
這樣的話會使用索引:???? select * from employee where last_name like ‘cliton%';
3、對Order By排序的列使用索引,避免使用表達(dá)式
ORDER BY語句決定了Oracle如何將返回的查詢結(jié)果排序。Order by語句對要排序的列沒有什么特別的限制,也可以將函數(shù)加入列中(象聯(lián)接或者附加等)。任何在Order by語句的非索引項或者有計算表達(dá)式都將降低查詢速度。仔細(xì)檢查order by語句以找出非索引項或者表達(dá)式,它們
會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應(yīng)絕對避免在order by
子句中使用表達(dá)式。
4、表記錄條數(shù)最小的寫在右邊
ORACLE 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最后的表(基礎(chǔ)表 driving table)將被最先處理,在FROM子句
中包含多個表的情況下,你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表。如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection
table)作為基礎(chǔ)表, 交叉表是指那個被其他表所引用的表.
5、避免使用select ' * '
ORACLE在解析的過程中, 會將’*’ 依次轉(zhuǎn)換成所有的列名, 這個工作是通過查詢數(shù)據(jù)字典完成的, 這意味著將耗費更多的時間
6、 減少訪問數(shù)據(jù)庫的次數(shù)
能使用一條sql語句查詢出來的最好使用一條語句直接查詢出來。? 整合簡單,無關(guān)聯(lián)的數(shù)據(jù)庫訪問: 如果你有幾個簡單的數(shù)據(jù)庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關(guān)系)
9、 用EXISTS替代IN、用NOT EXISTS替代NOT IN
在許多基于基礎(chǔ)表的查詢中,為了滿足一個條件,往往需要對另一個表進(jìn)行聯(lián)接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的
效率. 在子查詢中,NOT IN子句將執(zhí)行一個內(nèi)部的排序和合并. 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執(zhí)行了一個
全表遍歷). 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
例:
?(低效)select * from z_shangbiao u where u.ann_nnum!='' and u.ann_nnum? in( select e.user_account FROM? t_evaluation e)
(高效)select * from t_user u where u.account!='' and EXISTS( select e.user_account FROM? t_evaluation e where
u.account=e.user_account)
10、 用索引提高效率
雖然使用索引能得到查詢效率的提高,但是我們也必須注意到它的代價. 索引需要空間來存儲,也需要定期維護(hù), 每
當(dāng)有記錄在表中增減或索引列被修改時, 索引本身也會被修改. 這意味著每條記錄的INSERT , DELETE , UPDATE將為此多付出4 , 5 次的磁
盤I/O . 因為索引需要額外的存儲空間和處理,那些不必要的索引反而會使查詢反應(yīng)時間變慢.。定期的重構(gòu)索引是有必要的.:
11、用EXISTS替換DISTINCT
當(dāng)提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查
詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結(jié)果. 例子:
(低效):
SELECT? DISTINCT? DEPT_NO,DEPT_NAME? FROM? DEPT D , EMP E WHERE? D.DEPT_NO = E.DEPT_NO
(高效):
SELECT? DEPT_NO,DEPT_NAME? FROM? DEPT D? WHERE? EXISTS ( SELECT ‘X’ FROM? EMP E? WHERE E.DEPT_NO = D.DEPT_NO);
12、sql語句用大寫的
因為oracle總是先解析sql語句,把小寫的字母轉(zhuǎn)換成大寫的再執(zhí)行
13、 避免在索引列上使用計算.
WHERE子句中,如果索引列是函數(shù)的一部分.優(yōu)化器將不使用索引而使用全表掃描.
舉例:
低效:
SELECT … FROM? DEPT? WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
14、用>=替代>
高效:
SELECT * FROM? EMP? WHERE? DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
15、 用UNION替換OR (適用于索引列)
通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將造成全表掃描. 注意, 以上規(guī)則只針對多個索引列有效.
如果有column沒有被索引, 查詢效率可能會因為你沒有選擇OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引.
高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”
如果你堅持要用OR, 那就需要返回記錄最少的索引列寫在最前面.
16、 總是使用索引的第一個列
如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優(yōu)化器才會選擇使用該索引. 這也是一條簡單而重
要的規(guī)則,當(dāng)僅引用索引的第二個列時,優(yōu)化器使用了全表掃描而忽略了索引
例:比如你創(chuàng)建了索引(account,age,classno)三個字段為索引,那么你的sql語句使用where的時候應(yīng)該先使用account,此時才能使用索
引,如果你的where的第一個條件使用的是age或者classno那么將進(jìn)行全表搜索,而忽略了索引。
17、用UNION-ALL 替換UNION ( 如果有可能的話)
當(dāng)SQL 語句需要UNION兩個查詢結(jié)果集合時,這兩個結(jié)果集合會以UNION-ALL的方式被合并, 然后在輸出最終結(jié)果前進(jìn)行排序. 如果用UNION
ALL替代UNION, 這樣排序就不是必要了. 效率就會因此得到提高. 需要注意的是,UNION ALL 將重復(fù)輸出兩個結(jié)果集合中相同記錄. 因此各
位還是要從業(yè)務(wù)需求分析使用UNION ALL的可行性. UNION 將對結(jié)果集合排序,這個操作會使用到SORT_AREA_SIZE這塊內(nèi)存. 對于這塊內(nèi)存的
優(yōu)化也是相當(dāng)重要的. 下面的SQL可以用來查詢排序的消耗量
低效:
SELECT? ACCT_NUM, BALANCE_AMT
FROM? DEBIT_TRANSACTIONS
WHERE TRAN_DATE = ’31-DEC-95′
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = ’31-DEC-95′
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = ’31-DEC-95′
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = ’31-DEC-95′
18、避免改變索引列的類型
比如age字段為int型,然后你查詢的時候?qū)懙氖?where age='13',雖然查詢出來的結(jié)果是一樣的但是效率會降低,因為數(shù)據(jù)庫內(nèi)部多做了個
操作,自動對字符123 進(jìn)行TO_NUMBER(‘123′) 處理
19、 需要當(dāng)心的WHERE子句
某些SELECT 語句中的WHERE子句不使用索引. 這里有一些例子.
在下面的例子里, (1)‘!=’ 將不使用索引. 記住, 索引只能告訴你什么存在于表中, 而不能告訴你什么不存在于表中. (2) ‘||’是字符
連接函數(shù). 就象其他函數(shù)那樣, 停用了索引. (3) ‘+’是數(shù)學(xué)函數(shù). 就象其他數(shù)學(xué)函數(shù)那樣, 停用了索引. (4)相同的索引列不能互相比較,
這將會啟用全表掃描.
20、優(yōu)化GROUP BY,盡量使用where代替having
提高GROUP BY 語句的效率, 可以通過將不需要的記錄在GROUP BY 之前過濾掉.下面兩個查詢返回相同結(jié)果但第二個明顯就快了許多.
低效:
SELECT JOB , AVG(SAL)
FROM EMP
GROUP by JOB
HAVING JOB = ‘PRESIDENT’
OR JOB = ‘MANAGER’
高效:
SELECT JOB , AVG(SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT’
OR JOB = ‘MANAGER’
GROUP by JOB
本文章閱讀參考:http://www.jfox.info/SQL-you-hua.html 結(jié)合自己工作中使用,選擇性的分享,如果不對,歡迎提出
轉(zhuǎn)載于:https://www.cnblogs.com/zhuziyu/p/8921309.html
總結(jié)
- 上一篇: CC攻击(N个免费代理形成的DDOS)
- 下一篇: Could not install pa