今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於web應用尤其明顯。關於資料庫的效能,這並不只是dba才需要擔心的事,而這更是我 們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對運算元據庫時(尤其是查表時的sql語句),我們都需要注意資料操作的效能。這裡,我們不會講過 多的sql語句的優化,而只是針對mysql這一web應用最多的資料庫。希望下面的這些優化技巧對你有用。
1. 為查詢快取優化你的查詢
大多數的mysql伺服器都開啟了查詢快取。這是提高性最有效的方法之一,而且這是被mysql的資料庫引擎處理的。當有很多相同的查詢被執行了多次的時候,這些查詢結果會被放到乙個快取中,這樣,後續的相同的查詢就不用操作表而直接訪問快取結果了。
這裡最主要的問題是,對於程式設計師來說,這個事情是很容易被忽略的。因為,我們某些查詢語句會讓mysql不使用快取。請看下面的示例:
// 查詢快取不開啟上面兩條sql語句的差別就是 curdate() ,mysql的查詢快取對這個函式不起作用。所以,像 now() 和 rand() 或是其它的諸如此類的sql函式都不會開啟查詢快取,因為這些函式的返回是會不定的易變的。所以,你所需要的就是用乙個變數來代替mysql的函式,從而 開啟快取。$r= mysql_query(
"select username from user where signup_date >= curdate()"
); // 開啟查詢快取
$today
= date
("y-m-d"
); $r
= mysql_query(
"select username from user where signup_date >= '$today'"
);
2. explain 你的 select 查詢
使用 explain 關鍵字可以讓你知道mysql是如何處理你的sql語句的。這可以幫你分析你的查詢語句或是表結構的效能瓶頸。
explain 的查詢結果還會告訴你你的索引主鍵被如何利用的,你的資料表是如何被搜尋和排序的……等等,等等。
挑乙個你的select語句(推薦挑選那個最複雜的,有多表聯接的),把關鍵字explain加到前面。你可以使用phpmyadmin來做這個事。然後,你會看到一張**。下面的這個示例中,我們忘記加上了group_id索引,並且有表聯接:
當我們為 group_id 字段加上索引後:
我們可以看到,前乙個結果顯示搜尋了 7883 行,而後乙個只是搜尋了兩個表的 9 和 16 行。檢視rows列可以讓我們找到潛在的效能問題。
3. 當只要一行資料時使用 limit 1
當你查詢表的有些時候,你已經知道結果只會有一條結果,但因為你可能需要去fetch游標,或是你也許會去檢查返回的記錄數。
下面的示例,只是為了找一下是否有「中國」的使用者,很明顯,後面的會比前面的更有效率。(請注意,第一條中是select *,第二條是select 1)
// 沒有效率的:4. 為搜尋欄位建索引$r= mysql_query(
"select * from user where country = 'china'"
); if
(mysql_num_rows(
$r) > 0)
// 有效率的:
$r= mysql_query(
"select 1 from user where country = 'china' limit 1"
); if
(mysql_num_rows(
$r) > 0)
索引並不一定就是給主鍵或是唯一的字段。如果在你的表中,有某個欄位你總要會經常用來做搜尋,那麼,請為其建立索引吧。
從上圖你可以看到那個搜尋字串 「last_name like 『a%』」,乙個是建了索引,乙個是沒有索引,效能差了4倍左右。
5. 在join表的時候使用相當型別的例,並將其索引
如果你的應用程式有很多 join 查詢,你應該確認兩個表中join的字段是被建過索引的。這樣,mysql內部會啟動為你優化join的sql語句的機制。
而且,這些被用來join的字段,應該是相同的型別的。例如:如果你要把 decimal 欄位和乙個 int 欄位join在一起,mysql就無法使用它們的索引。對於那些string型別,還需要有相同的字符集才行。(兩個表的字符集有可能不一樣)
// 在state中查詢company6. 千萬不要 order by rand()$r= mysql_query("select company_name from users
left join companies on (users.state = companies.state)
where users.id = $user_id
");
// 兩個 state 字段應該是被建過索引的,而且應該是相當的型別,相同的字符集。
想打亂返回的資料行?隨機挑乙個資料?真不知道誰發明了這種用法,但很多新手很喜歡這樣用。但你確不了解這樣做有多麼可怕的效能問題。
如果你真的想把返回的資料行打亂了,你有n種方法可以達到這個目的。這樣使用只讓你的資料庫的效能呈指數級的下降。這裡的問題是:mysql會不得 不去執行rand()函式(很耗cpu時間),而且這是為了每一行記錄去記行,然後再對其排序。就算是你用了limit 1也無濟於事(因為要排序)
下面的示例是隨機挑一條記錄
// 千萬不要這樣做:$r= mysql_query(
"select username from user order by rand() limit 1"
); // 這要會更好:
$r= mysql_query(
"select count(*) from user"
); $d
= mysql_fetch_row(
$r);
$rand
= mt_rand(0,
$d[0] - 1);
$r= mysql_query(
"select username from user limit $rand, 1"
);
MySQL效能優化的最佳20 條經驗
今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於web應用尤其明顯。關於資料庫的效能,這並不只是dba才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對運算元據庫時 尤其是查表時的sql語句 我們都需要注意資料操作的效能。這裡,我們不會講過多的sql語句的...
MySQL效能優化的最佳20條經驗 技術文件
mysql效能優化的最佳20 條經驗 今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於 web應用尤其明顯。關於資料庫的效能,這並不只是 dba才需要擔心的事,而這更是我 們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對運算元據庫時 尤其是查表時的 sql 語句 我們都需要注意資...
Mysql效能優化20條經驗
1.為查詢快取優化你的查詢 2.explain 你的 select 查詢 3.當只要一行資料時使用 limit 1 4.為搜尋欄位建索引 5.在join表的時候使用相當型別的例,並將其索引 6.千萬不要 order by rand 7.避免 select 8.永遠為每張表設定乙個id 9.使用 en...