[摘 要]在數(shù)據(jù)庫系統(tǒng)中,數(shù)據(jù)查詢是一項及其重要的操作。影響數(shù)據(jù)庫系統(tǒng)性能的因素有很多,其中運用SQL語句的優(yōu)劣對數(shù)據(jù)庫系統(tǒng)的性能有直接的影響。優(yōu)化的SQL語句能夠提高數(shù)據(jù)庫系統(tǒng)的性能,從而實現(xiàn)高效的查詢,提高系統(tǒng)的可用性。
[關(guān)鍵詞]SQL 查詢 優(yōu)化
作者簡介:李增祥(1978,3-),學(xué)歷:研究生在讀,工作單位:山東理工大學(xué)計算機學(xué)院。
一、引言
在數(shù)據(jù)庫應(yīng)用系統(tǒng)中,相對于數(shù)據(jù)庫其它操作,查詢操作是最為重要的一部分, 在系統(tǒng)開發(fā)過程中,若不注重SQL的查詢策略,往往在剛開始應(yīng)用時比較流暢,但隨著數(shù)據(jù)庫表中記錄的日積月累數(shù)量越來越大,系統(tǒng)的響應(yīng)速度越來越慢,甚至讓人無法忍受 ,因此 ,查詢優(yōu)化也就有著非常重要的地位??茖W(xué)合理地構(gòu)造查詢系統(tǒng),是成功開發(fā)數(shù)據(jù)庫應(yīng)用系統(tǒng)非常重要的環(huán)節(jié)。據(jù)統(tǒng)計約有 90 %的性能問題是由于程序員或用戶使用了不恰當(dāng)?shù)牟樵冋Z句造成的,因此SQL語句的質(zhì)量對整個系統(tǒng)效率有重大關(guān)系。
DBMS處理查詢計劃的過程是:做完查詢語句的詞法、語法檢查之后,將語句提交給DBMS 的查詢優(yōu)化器,優(yōu)化器做完代數(shù)優(yōu)化和存取路徑的優(yōu)化之后。由預(yù)編譯模塊對語句進行處理并生成查詢規(guī)劃,然后在合適的時間提交給系統(tǒng)處理執(zhí)行,最后將執(zhí)行結(jié)果返回給用戶。雖然現(xiàn)在的數(shù)據(jù)庫產(chǎn)品在查詢優(yōu)化方面已經(jīng)做得越來越好,但由用戶提交的SQL 語句是系統(tǒng)優(yōu)化的基礎(chǔ),因此用戶所寫語句的優(yōu)劣至關(guān)重要。
二、優(yōu)化方法
一個好的查詢表達式不是基于純粹的理論假設(shè)及謂詞想像出來的,而是在實際的項目開發(fā)過程中總結(jié)的經(jīng)驗,本文就通過幾個常用的查詢優(yōu)化方法,結(jié)合舉例來說明SQL查詢語句優(yōu)化技術(shù)。
(一)合理建立和使用索引
索引是數(shù)據(jù)庫中重要的數(shù)據(jù)結(jié)構(gòu),是優(yōu)化的基礎(chǔ),建立索引的根本目的是提高查詢效率,索引的使用要恰到好處,其使用原則如下:
1.在經(jīng)常進行連接的列上建立索引,而不經(jīng)常連接的字段則由優(yōu)化器自動生成索引;
2.在頻繁進行排序或分組的字段上建立索引;
3.在條件表達式中經(jīng)常在不同值較多的列上建立索引,在不同值少的列上不要建立索引,例如在人事信息表中的“黨員”字段中,只有兩個不同的邏輯值:.T.和.F.這兩個值,所以就沒有必要建立索引。
例如:兩個表PEOPLE(編號,姓名,性別……)和WIFE(編號,姓名,性別….)
命令SELECT PEOPLE.編號,PEOPLE.姓名,WIFE.編號,WIFE.姓名 FROM PEOPLE,WIFE WHERE PEOPLE.編號=WIFE.編號
這兩個表要進行鏈接,就要在這兩個表上以“編號”為字段建立索引。
(二)避免使用不兼容的數(shù)據(jù)
最微妙的查詢問題之一就是在 WHERE 子句中,對具有不同類型的字段的比較,例如 FLOAT 與 INT ,CHAR 與 VARCHAR , BINARY 與 VARBINARY 是不兼容的,因此要求 WHERE 子句中表達式的數(shù)據(jù)類型是兼容的, 數(shù)據(jù)類型的不兼容可能使優(yōu)化器無法執(zhí)行一些本來可以進行的優(yōu)化操作。
例如,對于SQL 語句
SEL ECT 姓名 FROM PEOPLE WHERE 月收入 >1500
由于 WHERE 子句中, 字段月收入是貨幣型字段, 而1500是整型數(shù), 優(yōu)化器無法對其進行優(yōu)化, 并且 DBMS 要耗費一定的時間將整型數(shù)1500轉(zhuǎn)化成貨幣型字段后, 才能進行優(yōu)化, 才能與字段月收入比較。為此, 在編程時可將整型數(shù)1500先轉(zhuǎn)化成貨幣型字段, 而不要等到運行時由系統(tǒng)來轉(zhuǎn)化,即語句改為:
SEL ECT 姓名 FROM PEOPLE WHER 月收入 ≥$1500
(三)避免使用“<>”或“NOT”這樣的操作符
“<>”是排斥性的操作符 ,而不是包括性的操作符 ,這會使系統(tǒng)無法使用索引 ,而只能直接搜索表中的數(shù)據(jù) .
例如1:SELECT 姓名 FROM PEOPLE WHERE 月收入<>1500
2:SELECT姓名 FROM PEOPLE WHERE NOT(月收入=1500)
3: SELECT姓名 FROM PEOPLE WHERE 月收入>1500 OR 月收入<1500
從上面3個命令我們就可以看出第3個命令可以使用索引查詢,它的查詢速度是最快的。
(四)避免對搜索參數(shù)使用其它操作符如數(shù)學(xué)、字符串函數(shù)等
例如:SELEC 姓名FROM PEOPLE WHERE SUBSTR(姓名,1,2)=“李”
WHERE子句中對列的任何操作結(jié)果都是在 SQL語句運行時逐列計算得到的 ,因此它不得不進行表搜索 ,而沒有使用該列上面的索引 . 因此將 SQL 語句重寫成下面這樣:
SELEC姓名 FROM PEOPLE WHERE 姓名LIKE “李%”
這樣就提高了查詢的速度。
(五)避免使用IN語句
當(dāng)查詢語句中有 IN 關(guān)鍵詞時 ,優(yōu)化器采用 OR并列條件。例如:
SELECT 姓名 FROM PEOPLE WHERE 編號 IN (“1002”,”1004”)
數(shù)據(jù)庫系統(tǒng)轉(zhuǎn)化為:
SELECT 姓名 FROM PEOPLE WHERE 編號=“1002”O(jiān)R 編號=“1004”
在命令中,當(dāng)可以使用IN或者EXIST時, EXISTS遠比 IN 的效率高。在操作中如果把所有的 IN 操作符子查詢改寫為使用EXISTS的子查詢 ,這樣效率更高。同理 ,使用 NOT EXIST代替NOT IN會使查詢添加限制條件 ,由此減少全表掃描次數(shù) ,從而加快查詢的速度以達到提高數(shù)據(jù)庫運行效率。
(六)避免對查找條件使用各種運算符
對查詢條件使用各種運算符,數(shù)據(jù)庫系統(tǒng)在執(zhí)行時,首先計算運算表達式的值,這樣就影響系統(tǒng)的運算速度,例如:
1)SELECT * FROM PEOPLE WHERE 月收入*12>24000
2) SELECT * FROM PEOPLE WHERE 月收入>2000
這兩個命令的查詢結(jié)果是一樣的,但是第一條命令首先計算表達式的值,然后再參與查詢,而第二條命令則是直接查詢,查詢效率明顯比第一條命令高。
三、結(jié)束語
編寫優(yōu)劣SQL語句是提高影響數(shù)據(jù)庫系統(tǒng)的重要因素,對于數(shù)據(jù)庫系統(tǒng),不是僅僅實現(xiàn)功能即可,還要追求起執(zhí)行的效率,在本文中,說明了在查詢中編寫SQL語句應(yīng)該注意的問題,在大多數(shù)的情況下,需要反復(fù)試驗不同的SQL語句才能得到最佳的方案。
參考文獻
[1]薩師煊,數(shù)據(jù)庫系統(tǒng)概論,高等教育出版社 1990.5
[2]何海賓,數(shù)據(jù)庫查詢過程優(yōu)化技術(shù),西南民族大學(xué)學(xué)報 2-2004