[摘要]基于關系數據庫的標準查詢語言SQL在數據庫系統中被廣泛使用,在使用SQL查詢和檢索數據時往往只注重正確性,忽略其效率性。從SQL查詢語句執行過程入手,先解析執行過程,然后根據執行過程提出優化策略,使其在正確前提下,提高其運行效率。
[關鍵詞]關系數據庫SQL查詢對策
中圖分類號:TP3文獻標識碼:A文章編號:1671-7597(2009)1210080-01
在各類大型應用軟件的數據庫中,都存在大量的數據信息和記錄,經常要對它們進行各種數據操作。SQL(Structrued Query Language)作為結構化查詢語言,是大型計算機操作關系數據庫的標準查詢語言,同時也廣泛地應用到小型計算機的數據庫管理系統中。它是一種高度非過程化的語言,即只要用戶按其語法規則寫出符合操作要求的語句,而并不需要告訴系統應如何執行SQL語句,就可得到所要求的結果。隨著數據庫技術的廣泛應用,在數據庫程序的開發過程中,大量的工作是要進行數據查詢和檢索處理。本文從SQL查詢語句執行的過程入手,對其執行效率進行分析,并給出參考性建議和優化策略。
一、SQL語句執行過程解析
在平時書寫SQL查詢語句時,雖然每個人的寫法不盡相同,而且有時個別子句順序并不影響操作結果,但是在各種數據庫管理系統中,標準的SQL的解析順序為:
1.FROM子句,組裝來自不同數據源的數據;
2.WHERE子句,基于指定的條件對記錄進行篩選;
3.GROUP BY子句,將數據劃分為多個分組;
4.使用聚合函數進行計算;
5.使用HAVING子句篩選分組;
6.計算所有的表達式;
7.使用ORDER BY對結果集進行排序。
通過以上SQL語句的解析過程,我們可以對SQL查詢語句進行優化處理。SQL查詢語句的核心結構是SELECT…FROM…WHERE,了解了這個基本結構,我們可以從以下幾個方面對其進行優化處理。
二、效率分析及優化對策
(一)從From子句入手
From子句后面接單表或者多表,通常情況下接受來自不同數據源的多表。如果是單表,一般情況下對表進行快速全表掃描。如果是多表的情況,查詢設計優化器將采取自右向左的順序依次讀取數據表。如以下語句:“From table1,table2,table3”,優化器將優先讀取table3表,然后是table2表,最后是table1表。在進行From子句的多表連接時,就需要結合條件子句WHERE進行分析,需要遵循下面的規則:1. 當WHERE后面接的條件能夠一次性過濾某個表的大量記錄時,應優先處理該表。2. 如果WHERE后面接的條件不能過濾掉大量記錄時應該優先考慮處理記錄數最少或者索引關鍵值最少的表。
(二)從條件子句WHERE入手
WHERE子句后面通常接過濾條件,對表的記錄進行篩選,篩選出符合條件的記錄。如果SELECT查詢語句沒有WHERE子句,則無須對表記錄進行過濾。若后面接單個表,則通常順序掃描全表。若后接多表或者大量記錄表時,則可以考慮用索引來減少查詢的時間。所以在查詢前可對各個表建立比較的索引。對WHERE子句中出現的條件,可以依據以下原則首先來驅動查詢。
(1)建立索引字段的列比沒有建立索引的要快;(2)主索引要比普通索引快;(3)單索引要比符合索引快;(4)有條件約束要比沒有條件約束要快。
此外,WHERE子句通常采用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前,那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。根據以上原則,我們可以判斷出以下四個語句中哪個選項語句效率最高。
Select * Frommobilewhere (mobileno='13775637677') andbegINtime>
{^2009-1-308:20:11} andbegintime<{^2009-9-308:20:11}
B) SELECT*Frommobilewhere(mobileno='13775637677' )andbegINtime<
{^2009-1-30 8:20:11} andbegintime>{^2009-1-30 8:20:11}
C) SELECT*Frommobilewherebegintime<{^2009-9-30 8:20:11}andbegINtime>
{^2009-1-308:20:11}and(mobileno='13775637677' )
很顯然,綜合以上原則C選項效率最高。
(三)從GROUP BY和HAVING子句入手
在SELECT語句中,GROUP BY語句的作用是對記錄進行分組(劃分成較小的組),使用聚合函數返回每一個組的匯總信息,而HAVING子句限制返回的結果集。在一個SQL語句中可以有WHERE子句和HAVING子句。HAVING與WHERE子句類似,均用于設置限定條件。WHERE子句的作用是在對查詢結果進行分組前,將不符合WHERE條件的記錄過濾掉,而HAVING子句的作用是篩選滿足條件的組,即在分組之后過濾數據,但它不能單獨使用,只能配合GROUP By語句使用,該條件中經常包含聚組函數,使用HAVING條件顯示特定的組,也可以使用多個分組標準進行分組。雖然HAVING子句可以起到過濾的作用,但是要盡量避免使用HAVING子句,HAVING只會在檢索出所有記錄之后才對結果集進行過濾。這個處理需要排序,總計等操作。如果能通過WHERE子句限制記錄的數目,而且能盡早地把不滿足條件的記錄過濾掉,那就能減少這方面的開銷。
(四)從謂詞等方面入手
在SELECT語句中,由于實際需要,查詢語句會經常出現謂詞。常用的謂詞有EXIST,NOT EXSIT,IN,NOT IN等,巧用謂詞也會提高SQL語句的執行效率,可參考以下原則編寫SQL語句。
1.Where子句中盡量不要使用IS NULL或IS NOT NULL的語句,因為它們不會使用索引。
2.WHERE子句盡量不要將通配符(%)放在搜尋詞首出現,通配符(%)在搜尋詞首出現不會使用索引。
3.用EXISTS代替IN。在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接。在這種情況下,使用EXISTS(或NOT EXISTS)通常將提高查詢的效率。
4.用表連接代替EXISTS。通常來說,采用表連接的方式比EXISTS更有效率。
5.用EXISTS代替DISTINCT。當提交一個包含一對多表信息(比如班級表和學生表)的查詢時,避免在SELECT子句中使用DISTINCT。一般可以考慮用EXIST替換。
6.WHERE子句盡量少使用NOT或是<>,應該成OR來實行,使用OR時應該把結果集小的條件放在前面。
7.UNION改用UNION ALL,UNION要對合并的結果進行排序,UNION ALL不排序。
8.ORDER BY子句中盡量不要使用非索引列。
三、結語
通過對SQL查詢語句執行過程的分析,可以從以上幾個方面對其進行優化改進,從而提高了數據庫查詢和檢索的效率。當然,具體的查詢語句還要根據具體需要,并結合具體的數據庫系統而定。只有多總結多積累才能寫出高質量高效率的查詢語句,當然這只是提高數據檢索的一個方面,在其他方面的設計也要進行優化,如對表建立必要的索引,減少表之間的連接,或盡量在索引屬性列上建立連接等。總之,通過以上幾個方面的綜合優化,一定會使數據庫查詢與檢索效率有很大的提高。
參考文獻:
[1]王振輝、吳廣茂,SQL查詢語句優化研究[J].計算機應用,2005,25(12).
[2]徐鳳梅,關系數據庫中SQL查詢語言的優化策略[J].廣西輕工業,2009,126(5).
[3]鄧文艷,基于關系數據庫的查詢優化技術[J].太原科技,2007(12).
[4]楊克昌,Visual FoxPro程序設計教程[M].長沙:湖南科學技術出版社,2004.
[5]李瑩、代勤,關系代數運算與SQL查詢的對應關系[J].內蒙古農業大學學報(自然科學版),2003,24(3).
作者簡介:
彭易波,助教,主要研究方向:數據庫,無線傳感器,計算機應用。