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