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