1、資料庫空間是個概述,在sqlserver里,使用語句 exec sp_spaceused 'TableName' 這個語句來查。
Ⅱ 關於SQL資料庫優化
具體要注意的:
1.應盡量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0
2.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜索該表的所有行。
3.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
4.in 和 not in 也要慎用,因為IN會使系統無法使用索引,而只能直接搜索表中的數據。如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
5.盡量避免在索引過的字元數據中,使用非打頭字母搜索。這也使得引擎無法利用索引。
見如下例子:
SELECT * FROM T1 WHERE NAME LIKE 『%L%』
SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=』L』
SELECT * FROM T1 WHERE NAME LIKE 『L%』
即使NAME欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有數據逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。
6.必要時強制查詢優化器使用某個索引,如在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變數,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
7.應盡量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
SELECT * FROM T1 WHERE F1/2=100
應改為:
SELECT * FROM T1 WHERE F1=100*2
SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=』5378』
應改為:
SELECT * FROM RECORD WHERE CARD_NO LIKE 『5378%』
SELECT member_number, first_name, last_name FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
應改為:
SELECT member_number, first_name, last_name FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何對列的操作都將導致表掃描,它包括資料庫函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊。
8.應盡量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--『2005-11-30』生成的id
應改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
9.不要在 where 子句中的「=」左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
10.在使用索引欄位作為條件時,如果該索引是復合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓欄位順序與索引順序相一致。
11.很多時候用 exists是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select top 1 from b where num=a.num)
SELECT SUM(T1.C1)FROM T1 WHERE(
(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
SELECT SUM(T1.C1) FROM T1WHERE EXISTS(
SELECT * FROM T2 WHERE T2.C2=T1.C2)
兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。
如果你想校驗表裡是否存在某條紀錄,不要用count(*)那樣效率很低,而且浪費伺服器資源。可以用EXISTS代替。如:
IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')
可以寫成:
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
經常需要寫一個T_SQL語句比較一個父結果集和子結果集,從而找到是否存在在父結果集中有而在子結果集中沒有的記錄,如:
SELECT a.hdr_key FROM hdr_tbl a---- tbl a 表示tbl用別名a代替
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)
SELECT a.hdr_key FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL
SELECT hdr_key FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
三種寫法都可以得到同樣正確的結果,但是效率依次降低。
12.盡量使用表變數來代替臨時表。如果表變數包含大量數據,請注意索引非常有限(只有主鍵索引)。
13.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
14.臨時表並不是不可使用,適當地使用它們可以使某些常式更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。
15.在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然後insert。
16.如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。
17.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句後向客戶端發送 DONE_IN_PROC 消息。
18.盡量避免大事務操作,提高系統並發能力。
19.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。
20. 避免使用不兼容的數據類型。例如float和int、char和varchar、binary和varbinary是不兼容的。數據類型的不兼容可能使優化器無法執行一些本來可以進行的優化操作。例如:
SELECT name FROM employee WHERE salary > 60000
在這條語句中,如salary欄位是money型的,則優化器很難對其進行優化,因為60000是個整型數。我們應當在編程時將整型轉化成為錢幣型,而不要等到運行時轉化。
21.充分利用連接條件,在某種情況下,兩個表之間可能不只一個的連接條件,這時在 WHERE 子句中將連接條件完整的寫上,有可能大大提高查詢速度。
例:
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO
第二句將比第一句執行快得多。
22、使用視圖加速查詢
把表的一個子集進行排序並創建視圖,有時能加速查詢。它有助於避免多重排序 操作,而且在其他方面還能簡化優化器的工作。例如:
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
AND cust.postcode>「98000」
ORDER BY cust.name
如果這個查詢要被執行多次而不止一次,可以把所有未付款的客戶找出來放在一個視圖中,並按客戶的名字進行排序:
CREATE VIEW DBO.V_CUST_RCVLBES
AS
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
ORDER BY cust.name
然後以下面的方式在視圖中查詢:
SELECT * FROM V_CUST_RCVLBES
WHERE postcode>「98000」
視圖中的行要比主表中的行少,而且物理順序就是所要求的順序,減少了磁碟I/O,所以查詢工作量可以得到大幅減少。
23、能用DISTINCT的就不用GROUP BY
SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID
可改為:
SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10
24.能用UNION ALL就不要用UNION
UNION ALL不執行SELECT DISTINCT函數,這樣就會減少很多不必要的資源
35.盡量不要用SELECT INTO語句。
SELECT INOT 語句會導致表鎖定,阻止其他用戶訪問該表。
上面我們提到的是一些基本的提高查詢速度的注意事項,但是在更多的情況下,往往需要反復試驗比較不同的語句以得到最佳方案。最好的方法當然是測試,看實現相同功能的SQL語句哪個執行時間最少,但是資料庫中如果數據量很少,是比較不出來的,這時可以用查看執行計劃,即:把實現相同功能的多條SQL語句考到查詢分析器,按CTRL+L看查所利用的索引,表掃描次數(這兩個對性能影響最大),總體上看詢成本百分比即可。
今天在itput上看了一篇文章,是討論一個語句的優化:
原貼地址: http://www.itpub.net/viewthread.php?tid=1015964&extra=&page=1
一,發現問題 優化的語句:
請問以下語句如何優化:
CREATE TABLE aa_001
( ip VARCHAR2(28),
name VARCHAR2(10),
password VARCHAR2(30) )
select * from aa_001 where ip in (1,2,3) order by name desc;
--目前表中記錄有一千多萬條左右,而且in中的值個數是不確定的。
以上就是優化的需要優化的語句和情況。
不少人在後面跟帖:有的說沒辦法優化,有的說將IN該為EXISTS,有的說在ip上建立索引復合索引(ip,name)等等。
二,提出問題 那這樣的情況,能優化嗎,如何優化?今天就來討論這個問題。
三,分析問題 1,數據量1千萬多條。
2,in中的值個數是不確定
3.1 分析數據分布 這里作者沒有提到ip列的數據的分布情況,目前ip列的數據分布可能有以下幾種:
1,ip列(數據唯一,或者數據重復的概率很小)
2,ip列 (數據不均勻,可能有些數據重復多,有些重復少)
3,ip列 (數據分布比較均勻,數據大量重復,主要就是一些同樣的數據(可能只有上萬級別不同的ip數據等)
解決問題:
1,對於第一種數據分布情況,只要在ip列建立一個索引即可。這時不管表有多少行, in個數是不確定的情況下,都很快。
2,對應第二中數據分布情況,在ip列建立索引,效果不好。因為數據分布不均勻,可能有些快,有些慢
3,對應第三種數據分布情況,在ip列建立索引,速度肯定慢。
注意:這里的 order by name desc 是在取出數據後再排序的。而不是取數據前排序
對於2,3兩個情況,因為都是可能需要取出大量的數據,優化器就採用表掃描(table scan),而不是索引查找(index seek) ,速度很慢,因為這時表掃描效率要優於索引查找,特別是高並發情況下,效率很低。
那對應2,3中情況,如何處理。是將in改成exists。其實在sql server 2005和oracle里的優化器在in後面數據少時,效率是一樣的。這時採用一般的索引效率很低。這時如果在ip列上建立聚集索引,效率會比較高。我們在SQL server 2005中做個測試。
表:[dbo].[[zping.com]]]中有約200萬條數據。包含列Userid, id, Ruleid等列。按照上面的情況查詢一下類似語句:
select * from [dbo].[[zping.com]]] where
userid in ('',''
,'') order by Ruleid desc
我們先看userid的數據分布情況,執行下面語句:
select userid,count(*) from [dbo].[[zping.com]]] group by userid order by 2
這時我們看看數據分布:總共有379條數據,數據兩從1到15萬都有,數據分布傾斜嚴重。下圖是其中一部分。
這時如果在ip上建立非聚集索引,效率很低,而且就是強行索引掃描,效率也很低,會發現IO次數比表掃描還高。這時只能在ip上建立聚集索引。這時看看結果。
這時發現,搜索採用了(clustered index seek)聚集搜索掃描。
在看看查詢返回的結果:
(156603 行受影響)
表 '[zping.com]'。掃描計數 8,邏輯讀取 5877 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 'Worktable'。掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
返回15萬行,才不到6千次IO。效率較高,因為這15萬行要排序,查詢成本里排序佔了51%。當然可以建立(userid,Ruleid)復合聚集索引,提高性能,但這樣做DML維護成本較高。建議不採用。
從上面的測試例子可以看出, 優化的解決辦法:
數據分布為1:建立ip索引即可
數據分布為2,3:在ip列建立聚集索引。
Ⅲ 如何優化用SQL語句INSERT INTO
如何優化用SQL語句INSERT INTO
T-SQL腳本優化技巧:
1)對於SELECT/UPDATE語句必須顯示的定義所有的列,避免使用星號。
2)在執行SELECT/INSERT/UPDATE/DELETE語句時,請考慮執行規劃的重用,盡量考慮用SP-EXECUTESQL存儲過程。
3)優先使用 SELECT...INTO,然後使用 INSERT...SELECT,以避免大量死鎖。
4)如果需要刪除所有的數據,用TRUNCATE TABLE 代替DELETE 。
5)避免使用DISTINCT 語句。
6)如果你需要有限的記錄,通過TOP N代替SET ROWCOUNT來控制排序取值。
7)避免使用SARGABLE的語句在WHERE子句,比如: OR, <>, !=, !<, >!, IS NULL, NOT, NOT IN, NOT LIKE 和LIKE,因為這些操作很難利用已知的索引。
8)避免使用NOT IN,可以採用IN,EXISTS NOT EXISTS和LEFT JOIN 加空值判斷
--NOT EXISTS, 效率最高 SELECT a.hdr_key
FROM hdr_tbl a
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key) --LEFT JOIN SELECT a.hdr_key
FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key
WHERE b.hdr_key IS NULL --NOT IN ,效率最低 SELECT hdr_key
FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl) 9)使用EXISTS判斷記錄是否存在。
--不好的寫法: IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx') --正確的寫法: IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx') 10)避免在GROUP BY中使用HAVING 語句。
11)GROUP BY的語句要盡量簡單,不要進行GROUP BY語句的嵌套,避免在GROUP BY中包含多餘的列
考慮在GROUP BY的列,進行ORDER BY排序,特別在多用戶的環境下。
12)如果需要在一個包含JOIN的SELECT語句進行GROUP BY,請考慮用子查詢代替JOIN. 如果必須使用GROUP BY, GROUP BY 的應該列在同一張表。
13)如果WHERE條件語句有多個AND條件,請確保至少有一個列有索引,如果沒有可以建立多列復合INDEX。
14)對於SQL 無法執行自動優化的WHERE條件語句,可以通過HINTS顯示的制定INDEX來提高查詢的效率。
--可能不好的寫法: SELECT * FROM tblTaskProcessesWHERE nextprocess = 1 AND processid IN (8,32,45) --正確的寫法: SELECT * FROM tblTaskProcesses (INDEX = IX_ProcessID)WHERE nextprocess = 1 AND processid IN (8,32,45) 15)盡可能避免在WHERE條件語句中使用函數計算。
--不好的寫法: WHERE SUBSTRING(firstname,1,1) = 'm' --正確的寫法: WHERE firstname like 'm%' 16)在WHERE條件語句中,避免在函數中包列,如果無法避免,請考慮在該列建立INDEX。
Ⅳ 項目中優化sql語句執行效率的方法是什麼
1. SQL優化的原則是:將一次操作需要讀取的BLOCK數減到最低,即在最短的時間達到最大的數據吞吐量。 調整不良SQL通常可以從以下幾點切入: ? 檢查不良的SQL,考慮其寫法是否還有可優化內容 ? 檢查子查詢 考慮SQL子查詢是否可以用簡單連接的方式進行重新書寫 ? 檢查優化索引的使用 ? 考慮資料庫的優化器 2. 避免出現SELECT * FROM table 語句,要明確查出的欄位。 3. 在一個SQL語句中,如果一個where條件過濾的資料庫記錄越多,定位越准確,則該where條件越應該前移。 4. 查詢時盡可能使用索引覆蓋。即對SELECT的欄位建立復合索引,這樣查詢時只進行索引掃描,不讀取數據塊。 5. 在判斷有無符合條件的記錄時建議不要用SELECT COUNT (*)和select top 1 語句。 6. 使用內層限定原則,在拼寫SQL語句時,將查詢條件分解、分類,並盡量在SQL語句的最里層進行限定,以減少數據的處理量。 7. 應絕對避免在order by子句中使用表達式。 8. 如果需要從關聯表讀數據,關聯的表一般不要超過7個。 9. 小心使用 IN 和 OR,需要注意In集合中的數據量。建議集合中的數據不超過200個。 10. <> 用 < 、 > 代替,>用>=代替,<用<=代替,這樣可以有效的利用索引。 11. 在查詢時盡量減少對多餘數據的讀取包括多餘的列與多餘的行。 12. 對於復合索引要注意,例如在建立復合索引時列的順序是F1,F2,F3,則在where或order by子句中這些欄位出現的順序要與建立索引時的欄位順序一致,且必須包含第一列。只能是F1或F1,F2或F1,F2,F3。否則不會用到該索引。 13. 多表關聯查詢時,寫法必須遵循以下原則,這樣做有利於建立索引,提高查詢效率。格式如下select sum(table1.je) from table1 table1, table2 table2, table3 table3 where (table1的等值條件(=)) and (table1的非等值條件) and (table2與table1的關聯條件) and (table2的等值條件) and (table2的非等值條件) and (table3與table2的關聯條件) and (table3的等值條件) and (table3的非等值條件)。 注:關於多表查詢時from 後面表的出現順序對效率的影響還有待研究。 14. 子查詢問題。對於能用連接方式或者視圖方式實現的功能,不要用子查詢。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。應該用如下語句代替:select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100。 15. 在WHERE 子句中,避免對列的四則運算,特別是where 條件的左邊,嚴禁使用運算與函數對列進行處理。比如有些地方 substring 可以用like代替。 16. 如果在語句中有not in(in)操作,應考慮用not exists(exists)來重寫,最好的辦法是使用外連接實現。 17. 對一個業務過程的處理,應該使事物的開始與結束之間的時間間隔越短越好,原則上做到資料庫的讀操作在前面完成,資料庫寫操作在後面完成,避免交叉。 18. 請小心不要對過多的列使用列函數和order by,group by等,謹慎使用disti軟體開發t。 19. 用union all 代替 union,資料庫執行union操作,首先先分別執行union兩端的查詢,將其放在臨時表中,然後在對其進行排序,過濾重復的記錄。 當已知的業務邏輯決定query A和query B中不會有重復記錄時,應該用union all代替union,以提高查詢效率。
Ⅳ 做測試不會 SQL超詳細的 SQL 查詢語法教程來啦
作為一名測試工程師,工作中在對測試結果進行數據比對的時候,或多或少要和資料庫打交道的,要和資料庫打交道,那麼一些常用的 SQL 查詢語法必須要掌握。最近有部分做測試小夥伴表示 SQL 查詢不太會,問我有沒有 SQL 查詢語法這一塊的文檔可以學習,於是我就整理了這篇超詳細的 SQL 查詢語法教程,來給大家參考學習!
創建資料庫、數據表
學生表欄位說明
班級表欄位說明
准備數據
使用 where 子句對表中的數據篩選,結果為 true 的行會出現在結果集中
例 1:查詢編號大於 3 的學生
例 2:查詢編號不大於 4 的學生
例 3:查詢姓名不是「關羽」的學生
例 4:查詢沒被刪除的學生
例 5:查詢編號大於 3 的女同學
例 6:查詢編號小於 4 或沒被刪除的學生
例 7:查詢姓黃的學生
例 8:查詢姓黃並且「名」是一個字的學生
例 9:查詢姓劉或叫飛的學生
例 10:查詢編號是 1 或 3 或 8 的學生
例 11:查詢編號為 3 至 8 的學生
例 12:查詢編號是 3 至 8 的男生
例 13:查詢沒有填寫身高的學生
例 14:查詢填寫了身高的學生
例 15:查詢填寫了身高的男生
為了方便查看數據,可以對數據進行排序
語法:
說明
例 1:查詢未刪除男生信息,按學號降序
例 2:查詢未刪除學生信息,按名稱升序
例 3:顯示所有的學生信息,先按照年齡從大--> 小排序,當年齡相同時 按照身高從高--> 矮排序
為了快速得到統計數據,經常會用到如下 5 個聚合函數
例 1:查詢學生總數
例 2:查詢女生的編號最大值
例 3:查詢未刪除的學生最我號
例 4:查詢男生的總年齡
例 5:查詢未刪除女生的編號平均值
根據 gender 欄位來分組,gender 欄位的全部值有 4 個'男','女','中性','保密',所以分為了 4 組 當 group by 單獨使用時,只顯示出每組的第一條記錄, 所以 group by 單獨使用時的實際意義不大
當數據量過大時,在一頁中查看數據是一件非常麻煩的事情,這個時候就需要多數據進行分頁,下面來看看 SQL 分頁查詢
語法
說明
例 1:查詢前 3 行男生信息
示例:分頁
子查詢
子查詢分類
標量子查詢
查詢班級學生的平均年齡
列級子查詢
行級子查詢
子查詢中特定關鍵字使用
當查詢結果的列來源於多張表時,需要將多張表連接成一個大的數據集,再選擇合適的列返回,這中情況下就需要使用到連接查詢了,下面給大家介紹一下常用的 3 中連接查詢語法:
常用的連接查詢語法就給大家介紹到這里了,更多的連接查詢語法大家可以擴展學習
Ⅵ 查詢的SQL語句怎麼寫才能提高查詢效率
這是SQL語句優化的問題了。網上好多類似的文章,非常全面。
個人覺得比較常用的是:
SQL語句查詢中經常用到的欄位建索引,這樣可以非常明顯的提升查詢速度。
FROM表的順序,大表在前,小表在後,因為檢索的順序從後往前。
WHERE, WHERE A.COLUMN = B.COLUMN,把小表的欄位放在後邊(B表),大表在前。
固定值查詢的放在後邊 COLUMN = '1'這種。因為這個也是從後往前的順序。
如果有(NOT) IN (SELECT ...) 盡量避免,因為IN裡面也是一個大的查詢,使用 (NOT) EXISTS的語法代替。
還有UNION和UNION ALL,多表聯合,UNION的作用是可以去掉重復,如果多表沒有重復數據,使用UNION ALL效率也會大大提高。
Ⅶ 帆軟SQL 語句優化
SELECT DISTINCT * --(這個*一定要寫具體欄位,有助於提高查詢速度)
FROM dbo.[dksj],dbo.[pkhlb1]
WHERE dbo.[dksj].證件號碼 *= dbo.[pkhlb1].證件號碼
AND 證件號碼 = '${sfz}'
Ⅷ SQL 語句優化,該怎麼處理
(1)選擇最有效率的表名順序(只在基於規則的優化器中有效):
ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫
在最後的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的
情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連接查詢
, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其
他表所引用的表.
(2) WHERE子句中的連接順序.:
ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必
須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE
子句的末尾.
(3) SELECT子句中避免使用『 * 『:
ORACLE在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過
查詢數據字典完成的, 這意味著將耗費更多的時間
(4)減少訪問資料庫的次數:
ORACLE在內部執行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變
量 , 讀數據塊等;
(5)在SQL*Plus , SQL*Forms和Pro*C中重新設置ARRAYSIZE參數, 可以增加
每次資料庫訪問的檢索數據量 ,建議值為200
(6)使用DECODE函數來減少處理時間:
使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表.
(7)整合簡單,無關聯的資料庫訪問:
如果你有幾個簡單的資料庫查詢語句,你可以把它們整合到一個查詢中(即使
它們之間沒有關系)
(8)刪除重復記錄:
最高效的刪除重復記錄方法 ( 因為使用了ROWID)例子:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
(9)用TRUNCATE替代DELETE:
當刪除表中的記錄時,在通常情況下, 回滾段(rollback segments ) 用來存
放可以被恢復的信息. 如果你沒有COMMIT事務,ORACLE會將數據恢復到刪除之前
的狀態(准確地說是恢復到執行刪除命令之前的狀況) 而當運用TRUNCATE時, 回
滾段不再存放任何可被恢復的信息.當命令運行後,數據不能被恢復.因此很少的
資源被調用,執行時間也會很短. (譯者按: TRUNCATE只在刪除全表適
用,TRUNCATE是DDL不是DML)
(10)盡量多使用COMMIT:
只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也
會因為COMMIT所釋放的資源而減少:
COMMIT所釋放的資源:
a. 回滾段上用於恢復數據的信息.
b. 被程序語句獲得的鎖
c. redo log buffer 中的空間
d. ORACLE為管理上述3種資源中的內部花費
(11)用Where子句替換HAVING子句:
避免使用HAVING子句, 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進行過濾。由此可見,要想過濾條件起到正確的作用,首先要明白這個條
件應該在什麼時候起作用,然後再決定放在那裡
(12)減少對表的查詢:
在含有子查詢的SQL語句中,要特別注意減少對表的查詢.例子:
SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
(13)通過內部函數提高SQL效率.:
復雜的SQL往往犧牲了執行效率. 能夠掌握上面的運用函數解決問題的方法
在實際工作中是非常有意義的
(14)使用表的別名(Alias):
當在SQL語句中連接多個表時, 請使用表的別名並把別名前綴於每個Column
上.這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤.
(15)用EXISTS替代IN、用NOT EXISTS替代NOT IN:
在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯
接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率. 在子查
詢中,NOT IN子句將執行一個內部的排序和合並. 無論在哪種情況下,NOT IN都是
最低效的 (因為它對子查詢中的表執行了一個全表遍歷). 為了避免使用NOT IN
,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
例子:
(高效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT
『X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 『MELB')
(低效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT
DEPTNO FROM DEPT WHERE LOC = 『MELB')
(16)識別'低效執行'的SQL語句:
雖然目前各種關於SQL優化的圖形化工具層出不窮,但是寫出自己的SQL工具
來解決問題始終是一個最好的方法:
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-
DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2)
Reads_per_run,
SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND
(BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;
(17)用索引提高效率:
索引是表的一個概念部分,用來提高檢索數據的效率,ORACLE使用了一個復
雜的自平衡B-tree結構. 通常,通過索引查詢數據比全表掃描要快. 當ORACLE找
出執行查詢和Update語句的最佳路徑時, ORACLE優化器將使用索引. 同樣在聯結
多個表時使用索引也可以提高效率. 另一個使用索引的好處是,它提供了主鍵
(primary key)的唯一性驗證.。那些LONG或LONG RAW數據類型, 你可以索引幾乎
所有的列. 通常, 在大型表中使用索引特別有效. 當然,你也會發現, 在掃描小
表時,使用索引同樣能提高效率. 雖然使用索引能得到查詢效率的提高,但是我們
也必須注意到它的代價. 索引需要空間來存儲,也需要定期維護, 每當有記錄在
表中增減或索引列被修改時, 索引本身也會被修改. 這意味著每條記錄的INSERT
, DELETE , UPDATE將為此多付出4 , 5 次的磁碟I/O . 因為索引需要額外的存
儲空間和處理,那些不必要的索引反而會使查詢反應時間變慢.。定期的重構索引
是有必要的.:
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
(18)用EXISTS替換DISTINCT:
當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在
SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查詢更為迅
速,因為RDBMS核心模塊將在子查詢的條件一旦滿足後,立刻返回結果. 例子:
(低效): 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);
(19) sql語句用大寫的;因為oracle總是先解析sql語句,把小寫的字母轉換成大寫的再執行
(20)在java代碼中盡量少用連接符「+」連接字元串!
Ⅸ sql 語句優化
tbl_pgw_refund_info:refund_req,result
tbl_pgw_refund_dtl :pay_brh_id
tbl_pgw_txn_dtl :order_id
TBL_PGW_TXN_DTL :int_txn_dt,rsp_code
TBL_PGW_PAY_DTL :order_id
在上述表的指定欄位上建索引