當今數據庫的操做愈來愈成爲整個應用的性能瓶頸,特別是Web應用更加明顯。當咱們設計數據庫和對數據庫操做時,都要考慮到性能。程序員
大多數MySQL服務器都開啓了查詢緩存,這是提升性能最有效的方案之一,並且這是被MySQL的數據庫引擎處理的。當有不少相同的查詢被執行多長的時候,這些下次結果會被放到一個緩存中,這樣後續相同的查詢就不須要操做表,而是直接從緩存中訪問結果。數據庫
這裏最主要的緣由是對於程序員來講,這個事情很容易被忽略。由於咱們的某些查詢語句不會讓MySQL生成緩存。以下示例:緩存
//查詢緩存不開啓 select username from user where reg_time = CURDATE(); //查詢緩存開啓 $today = date('Y-m-d'); select username from user where reg_time = '$today';
上面兩條SQL的區別在於CURDATE(),MySQL的查詢緩存對這個函數不起做用,像NOW()、RAND()等等諸如此類的SQL函數都不會開啓緩存,由於這些函數的返回是會變的。因此你要用一個變量來代替MySQL的函數,從而開啓緩存。服務器
使用EXPLAIN關鍵字可讓你知道MySQL是如何處理你的SQL語句的。這能夠幫你分析你的查詢語句或是表結構的性能瓶頸。網絡
EXPLAIN的查詢結果還會告訴你你的索引主鍵被如何利用的,你的數據表是如何被搜索和排序的……等等,等等。數據結構
挑一個你的SELECT語句(推薦挑選那個最複雜的,有多表聯接的),把關鍵字EXPLAIN加到前面。oracle
下面這個例子,咱們沒有給com_id添加索引:函數
當咱們給com_id字段添加索引後性能
咱們能夠很明顯的看到,前一個搜索結果檢索了3592行,然後一個只檢索了1行。fetch
當你查詢表的有些時候,你已經知道結果只會有一條結果,但由於你可能須要去fetch遊標,或是你也許會去檢查返回的記錄數。在這種狀況下,加上LIMIT 1能夠增長性能。這樣同樣,MySQL數據庫引擎會在找到一條數據後中止搜索,而不是繼續日後查少下一條符合記錄的數據。
索引並不必定就是給主鍵或是惟一的字段。若是在你的表中,有某個字段你總要會常常用來作搜索,那麼爲其創建索引。
若是你的應用程序有不少JOIN查詢,你應該確認兩個表中Join的字段是被建過索引的。這樣,MySQL內部會啓動爲你優化Join的SQL語句的機制。
並且,這些被用來Join的字段,應該是相同的類型的。例如:若是你要把DECIMAL字段和一個INT字段Join在一塊兒,MySQL就沒法使用它們的索引。對於那些STRING類型,還須要有相同的字符集才行。(兩個表的字符集有可能不同)
從數據庫裏讀的數據越多,查詢執行就越慢。而且,若是你的MySQL服務器和WEB服務器是兩個獨立的服務器,那麼還會增長網絡傳輸的負載。
咱們應該爲數據庫裏的每張表都設置一個ID作爲其主鍵,並且最好的是一個INT型的(推薦使用UNSIGNED),並設置上自動增長的AUTO_INCREMENT標誌。就算是你users表有一個主鍵叫「email」的字段,你也別讓它成爲主鍵。使用VARCHAR類型來當主鍵會使用得性能降低。另外,在你的程序中,你應該使用表的ID來構造你的數據結構。並且,在MySQL數據引擎下,還有一些操做須要使用主鍵,在這些狀況下,主鍵的性能和設置變得很是重要,好比,集羣,分區……
在這裏,只有一個狀況是例外,那就是「關聯表」的「外鍵」,也就是說,這個表的主鍵,經過若干個別的表的主鍵構成。咱們把這個狀況叫作「外鍵」。好比:有一個「學生表」有學生的ID,有一個「課程表」有課程ID,那麼,「成績表」就是「關聯表」了,其關聯了學生表和課程表,在成績表中,學生ID和課程ID叫「外鍵」其共同組成主鍵。
ENUM類型是很是快和緊湊的。在實際上,其保存的是TINYINT,但其外表上顯示爲字符串。這樣一來,用這個字段來作一些選項列表變得至關的完美。若是你有一個字段,好比「性別」,「國家」,「民族」,「狀態」或「部門」,你知道這些字段的取值是有限並且固定的,那麼,你應該使用ENUM而不是VARCHAR。
MySQL也有一個「建議」(見第9條)告訴你怎麼去從新組織你的表結構。當你有一個VARCHAR字段時,這個建議會告訴你把其改爲ENUM類型。使用PROCEDURE ANALYSE() 你能夠獲得相關的建議。
PROCEDURE ANALYSE() 會讓MySQL幫你去分析你的字段和其實際的數據,並會給你一些有用的建議。只有表中有實際的數據,這些建議纔會變得有用,由於要作一些大的決定是須要有數據做爲基礎的。
例如,若是你建立了一個INT字段做爲你的主鍵,然而並無太多的數據,那麼,PROCEDURE ANALYSE()會建議你把這個字段的類型改爲MEDIUMINT。或是你使用了一個VARCHAR字段,由於數據很少,你可能會獲得一個讓你把它改爲ENUM的建議。這些建議,都是可能由於數據不夠多,因此決策作得就不夠準。
除非你有一個很特別的緣由去使用NULL值,你應該老是讓你的字段保持NOT NULL。首先,問問你本身「Empty」和「NULL」有多大的區別(若是是INT,那就是0和NULL)?若是你以爲它們之間沒有什麼區別,那麼你就不要使用NULL。(你知道嗎?在Oracle裏,NULL 和 Empty的字符串是同樣的!)
不要覺得 NULL 不須要空間,其須要額外的空間,而且,在你進行比較的時候,你的程序會更復雜。固然,這裏並非說你就不能使用NULL了,現實狀況是很複雜的,依然會有些狀況下,你須要使用NULL值。