加快sql查詢是非常重要的技巧,簡單來說加快sql查詢的方式有以下幾種:
一、索引的引用
1、索引一般可以加速數據的檢索速度,加速表與表之間的鏈接,提高性能,所以在對海量數據進行處理時,考慮到信息量比較大,應該對表建立索引,包括在主鍵上建立聚簇索引,將聚合索引建立在日期刊上等。索引的優點有很多,但是對於索引的建立,還需要考慮實際情況,而不是對每一個列建立一個索引,比如針對大表的分組、排序等字段,都要建立相應索引,同時還應該考慮建立符合索引。增加索引的同時也有很多不好的方面,首先,創建索引和維護索引都耗費時間,且隨着數據量的增加而增加;其次,索引占據物理空間,聚簇索引的空間更大。最后,當對表進行增加、刪除和修改的時候,索引也要動態的維護。所以索引的引用有以下幾個原則:
(1)當插入數據為表中數據的百分之10以上時,首先需要刪除該表的索引來提高數據的插入效率,然后再重新建立索引;
(2)避免在索引列上使用函數或計算,在where字句中,如果索引是函數的一部分,優化器將不再使用索引,將使用全表掃描;例如:
select * from table where hh*10>1000;//低效 select * from table where hh>1000/10;//更高效
(3)盡量避免在索引列上使用not,!=和<>,索引只能告訴什么在表中,而不能告訴什么不在表中,當數據庫遇上以上幾種符號時,將不再使用索引,使用全表掃描
(4)檢索中不要對索引進行處理,如TRIM,TO_DATE,類型轉換等,這會破壞索引
(5)避免在索引列上使用IS NULL 或 IS NOT NULL。避免在索引列上使用任何可以為空的列,這樣將無法使用此索引。因為空值不存在於索引列中,所以當where字句中對索引進行空值比較,將無法使用該索引。
(6)在索引列上,使用>=代替>,比如:
select * from table where hh>10;//低效 select * from table where hh>=10.0000001//相對高效
二、SQL語句的優化
介紹幾種SQL語句的優化技巧:
(1)where字句中的鏈接順序
oracle采用自下而上的順序解析where字句,所以表之間的鏈接必須寫在其他where條件之前,那些可以濾過大量紀錄的條件必須寫在where字句的末尾,例如:
select * from table e where h>500 and d='001' and 25<(select count(*) from table where count=e.count); //低效 select * from table e where 25<(select count(*) from table where count=e.count); and h>500 and d='001';//更高效
(2)刪除全表時,用truncate而不用delete。因為truncate是ddl不是dml(truncate只能在刪除全表時使用),例如:
Truncate table account; 比 delete from account; 快1000倍
(3)盡量多使用commit,只要有可能就對程序中每個delete,insert,update使用commit,這樣系統會因為commit所釋放的資源而大大提高效率。
(4)用exists代替in,可以提高查詢的效率。例如:
SELECT * FROM ACCOUNT WHERE AC_CODE NOT IN ( SELECT CODE FROM GOODS WHERE NUM='001') //低效 SELECT * FROM ACCOUNT WHERE NOT EXISTS (SELECT CODE FROM GOODS WHERE CODE=ACCOUNT.AC_CODE AND NUM='001') //更高效
(5)使用group by
可以將不需要的語句在group by之前過濾掉
(6)避免使用HAVING字句
HAVING字句只有在檢索出所有記錄之后,才會對結果集進行過濾,這樣涉及到排序,統計等操作,如果能通過WHERE字句限制記錄的數目,就可以減少開銷。用Where子句替換HAVING子句,如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷. (非oracle中)on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最后,因為on是先把不 符合條件的記錄過濾后才進行統計,它就可以減少中間運算要處理的數據,按理說應該速度是最快的,where也應該比having快點的,因為它過濾數據后 才進行sum,在兩個表聯接時才用on的,所以在一個表的時候,就剩下where跟having比較了。在這單表查詢統計的情況下,如果要過濾的條件沒有涉及到要計算字段,那它們的結果是一樣的,只是where可以使用rushmore技術,而having就不能,在速度上后者要慢如果要涉及到計算的字 段,就表示在沒計算之前,這個字段的值是不確定的,根據上篇寫的工作流程,where的作用時間是在計算之前就完成的,而having就是在計算后才起作 用的,所以在這種情況下,兩者的結果會不同。在多表聯接查詢時,on比where更早起作用。系統首先根據各個表之間的聯接條件,把多個表合成一個臨時表 后,再由where進行過濾,然后再計算,計算完后再由having進行過濾。由此可見,要想過濾條件起到正確的作用,首先要明白這個條件應該在什么時候起作用,然后再決定放在那里 。
(7)有條件的使用union-all代替union提高效率
(8)在所有查詢的SQL語句中要特別注意減少對表的查詢,如:
(9)select字句中避免使用*
當想在select字句中列出所有的列時,使用*是一個很方便,但是很低效的方法,因為在oracle中,會通過查詢數據字典,將*依次轉換為所有的列名,很耗時
(10)Order by語句
ORDER BY語句決定了Oracle如何將返回的查詢結果排序。Order by語句對要排序的列沒有什么特別的限制,也可以將函數加入列中(象聯接或者附加等)。任何在Order by語句的非索引項或者有計算表達式都將降低查詢速度。仔細檢查order by語句以找出非索引項或者表達式,它們會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應絕對避免在order by子句中使用表達式。
(11)帶通配符(%)的like語句
目前的需求是這樣的,要求在職工表中查詢名字中包含cliton的人。可以采用如下的查詢SQL語句:
select * from employee where last_name like '%cliton%';
這里由於通配符(%)在搜尋詞首出現,所以Oracle系統不使用last_name的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,通配符如此使用會降低查詢速度。然而當通配符出現在字符串其他位置時,優化器就能利用索引。在下面的查詢中索引得到了使用:
select * from employee where last_name like 'c%';
(12)選擇最有效率的表名順序(只在基於規則的優化器中有效):
ORACLE 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最后的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表。
(13) 整合簡單,無關聯的數據庫訪問:
如果你有幾個簡單的數據庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關系)
(14)刪除重復記錄:
最高效的刪除重復記錄方法 ( 因為使用了ROWID)例子:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
(15)使用表的別名(Alias):
當在SQL語句中連接多個表時, 請使用表的別名並把別名前綴於每個Column上.這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤。
(16)sql語句用大寫的;因為oracle總是先解析sql語句,把小寫的字母轉換成大寫的再執行
(17) 在java代碼中盡量少用連接符“+”連接字符串!
(18) 總是使用索引的第一個列:
如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器才會選擇使用該索引. 這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引
三、函數的使用技巧
雖然有時肆意的使用函數,會將性能降低,但是用好函數有時也能提高性能和可讀性。如:
其他的一些方法可以參考http://www.cnblogs.com/ziyiFly/archive/2008/12/24/1361380.html