? ? ?因此,本文就在MySQL中常用的查詢優化技術進行討論。討論的內容如:通過查詢緩沖提高查詢速度;MySQL對查詢的自動優化;基于索引的排序;不可達查詢的檢測和使用各種查詢選擇來提高性能。
? ? ?
顯然,這對于頻繁更新的表,查詢緩存是不適合的,而對于一些不常改變數據且有大量相同sql查詢的表,查詢緩存會節約很大的性能。
通過查詢緩沖提高查詢速度
? ? ?一般我們使用SQL語句進行查詢時,數據庫服務器每次在收到客戶端發來SQL后,都會執行這條SQL語句。但當在一定間隔內(如1分鐘內),接到完 全一樣的SQL語句,也同樣執行它。雖然這樣可以保證數據的實時性,但在大多數時候,數據并不要求完全的實時,也就是說可以有一定的延時。如果是這樣的 話,在短時間內執行完全一樣的SQL就有些得不償失。
? ? ? 幸好MySQL為我們提供了查詢緩沖的功能(只能在MySQL 4.0.1及以上版本使用查詢緩沖)。我們可以通過查詢緩沖在一定程度上提高查詢性能。
? ? ? 我們可以通過在MySQL安裝目錄中的my.ini文件設置查詢緩沖。設置也非常簡單,只需要將query_cache_type設為1即可。在設 置了這個屬性后,MySQL在執行任何SELECT語句之前,都會在它的緩沖區中查詢是否在相同的SELECT語句被執行過,如果有,并且執行結果沒有過 期,那么就直接取查詢結果返回給客戶端。但在寫SQL語句時注意,MySQL的查詢緩沖是區分大小寫的。如下列的兩條SELECT語句:
1.??? SELECT * from TABLE1
2.
3.??? SELECT * FROM TABLE1
? ? ?上面的兩條SQL語句對于查詢緩沖是完全不同的SELECT。而且查詢緩沖并不自動處理空格,因此,在寫SQL語句時,應盡量減少空格的使用,尤其是在SQL首和尾的空格(因為,查詢緩沖并不自動截取首尾空格)。
? ? ? 雖然不設置查詢緩沖,有時可能帶來性能上的損失,但有一些SQL語句需要實時地查詢數據,或者并不經常使用(可能一天就執行一兩次)。這樣就需要把 緩沖關了。當然,這可以通過設置query_cache_type的值來關閉查詢緩沖,但這就將查詢緩沖永久地關閉了。在MySQL 5.0中提供了一種可以臨時關閉查詢緩沖的方法:
(1) SELECT SQL_NO_CACHE field1, field2 FROM TABLE1
以上的SQL語句由于使用了SQL_NO_CACHE,因此,不管這條SQL語句是否被執行過,服務器都不會在緩沖區中查找,每次都會執行它。
我們還可以將my.ini中的query_cache_type設成2,這樣只有在使用了SQL_CACHE后,才使用查詢緩沖。
(2) SELECT SQL_CALHE * FROM TABLE1
?
MySQL 檢查緩存命中的規則
(1)在檢查緩存的時候,MySQL 不會對語句進行解析、正則化或者參數化,它精確地使用客戶端傳來的查詢語句和其他數據。只要字符大小寫、空格或者注釋有一點點不同,查詢緩存就認為這是一個不同的查詢
(2)查詢緩存不會存儲有不確定結果的查詢。因此,任何一個包含不確定函數(比如NOW()或CURRENT_DATE())的查詢不會被緩存。同樣地,CURRENT_USER()或CONNECTION_ID()這些由不同用戶執行,將會產生不同的結果的查詢也不會被緩存。事實上,查詢緩存不會緩存引用了用戶自定義函數、存儲函數、用戶自定義變量、臨時表、mysql 數據庫中的表或者任何一個有列級權限的表的查詢
(3)查詢必須是完全相同的(逐字節相同)才能夠被認為是相同的。另外,同樣的查詢字符串由于其它原因可能認為是不同的。使用不同的數據庫、不同的協議版本或者不同 默認字符集的查詢被認為是不同的查詢并且分別進行緩存。
MySQL對查詢的自動優化
? ? ? 索引對于數據庫是非常重要的。在查詢時可以通過索引來提高性能。但有時使用索引反而會降低性能。我們可以看如下的SALES表:
1.??? CREATE TABLE SALES
2.
3.??? (
4.
5.??? ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
6.
7.??? NAME VARCHAR(100) NOT NULL,
8.
9.??? PRICE FLOAT NOT NULL,
10.
11.??? SALE_COUNT INT NOT NULL,
12.
13.??? SALE_DATE DATE NOT NULL,
14.
15.??? PRIMARY KEY(ID),
16.
17.??? INDEX (NAME),
18.
19.??? INDEX (SALE_DATE)
20.
21.??? );
? ? ?假設這個表中保存了數百萬條數據,而我們要查詢商品號為1000的商品在2004年和2005年的平均價格。我們可以寫如下的SQL語句:
SELECT AVG(PRICE) FROM SALES
WHERE ID = 1000 AND SALE_DATE BETWEEN ’2004-01-01′ AND ’2005-12-31′;
? ? ? 如果這種商品的數量非常多,差不多占了SALES表的記錄的50%或更多。那么使用SALE_DATE字段上索引來計算平均數就有些慢。因為如果使 用索引,就得對索引進行排序操作。當滿足條件的記錄非常多時(如占整個表的記錄的50%或更多的比例),速度會變慢,這樣還不如對整個表進行掃描。因 此,MySQL會自動根據滿足條件的數據占整個表的數據的比例自動決定是否使用索引進行查詢。
? ? ? 對于MySQL來說,上述的查詢結果占整個表的記錄的比例是30%左右時就不使用索引了,這個比例是MySQL的開發人員根據他們的經驗得出的。然而,實際的比例值會根據所使用的數據庫引擎不同而不同。
?
開啟查詢緩存的開銷
(1)讀取查詢在開始之前必須要檢查緩存。
(2)如果查詢是可以被緩存的,但是不在緩存中,那么在產生結果之后進行保存會帶來一些額外的開銷。 寫入數據的查詢也會有額外的開銷,因為它必須使緩存中相關的數據表失效。 ( 如果緩存中的數據,被刪除或跟新了,數據庫怎么判斷這個緩存的數據不能用了,是臟數據?)
? ? ?這些開銷相對來說較小,所以查詢緩存還是很有好處的。但是,稍后你會看到,額外的開銷有可能也會增加。從緩存中受益最多的查詢可能是需要很多資源來產生結果,但是不需要很多空間來保存的類型。所以用于存儲、返回和失效的代價都較小。聚集查詢,比如從大表中利用COUNT()產生較小的結果,就符合這個范疇。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
