mysql的性能優化總結

經驗是從別人那裏拿來的,不想直接複製黏貼,想親自總結下,巴拉巴拉.........進入正題吧php

1、爲查詢加入緩存html

一、檢查數據庫是否開啓緩存:show variables like '%query_cache%'; 若開啓query_cache_type 爲 ONmysql

二、設置查詢緩存的方法:網上搜素下:http://www.111cn.net/database/mysql/63815.htm(參考連接)web

使用緩存和不適用緩存的區別sql


$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'");;
二者惟一區別就是CURDATE(),查詢緩存對這個函數不起做用,項now()和rand()或者其餘sql函數均不會開啓查詢緩存,因此必須新增一個變量來代替mysql的函數,從而開啓緩存

2、EXPLAIN 你的 SELECT 查詢shell

查看rows列可讓咱們找到潛在的性能問題。數據庫

3、當只要一條數據時,使用limit1,性能會大大提高緩存

這樣mysql會在找到一條數據後中止搜索,而不是繼續日後查下一條符合記錄的數據服務器

下面的示例,只是爲了找一下是否有「中國」的用戶,很明顯,後面的會比前面的更有效率。(請注意,第一條中是Select *,第二條是Select 1)網絡

$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) {
    // ...
}

4、爲搜索字段加上索引

索引並不必定只是給主鍵和惟一的字段,加上索引,而是若是有某個字段常常會用到,則爲其加上索引

若是某個字段查詢時如 like「a%」,則能夠用上索引,可是若是想like「%a%」則索引沒意義

5、在使用join時,兩個表的字段類型要一致,,並且是被索引過的,myql內部會啓爲你優化join的字段

被join的字段應該是相同類型的。例如:若是你要把 DECIMAL 字段和一個 INT 字段Join在一塊兒,MySQL就沒法使用它們的索引。對於那些STRING類型,還須要有相同的字符集才行。(兩個表的字符集有可能不同)

$r = mysql_query("SELECT company_name FROM users
    LEFT JOIN companies ON (users.state = companies.state)
    WHERE users.id = $user_id");
 
// 兩個 state 字段應該是被建過索引的,並且應該是至關的類型,相同的字符集。

6、不要用select * 應該使用什麼字段就去取什麼字段,由於從數據庫讀越多的數據查詢就越慢,並且若是時web服務器和數據庫服務器時兩臺獨立的服務器還會增長網絡傳輸的負載

7、永遠爲每張表設置一個主鍵id

類型最好時int型的,varchar會使得性能降低, 推薦使用UNSIGNED),並設置上自動增長的AUTO_INCREMENT標誌。 在這裏,只有一個狀況是例外,那就是「關聯表」的「外鍵」,也就是說,這個表的主鍵,經過若干個別的表的主鍵構成。咱們把這個狀況叫作「外鍵」。好比:有一個「學生表」有學生的ID,有一個「課程表」有課程ID,那麼,「成績表」就是「關聯表」了,其關聯了學生表和課程表,在成績表中,學生ID和課程ID叫「外鍵」其共同組成主鍵。

8、使用enum而不是varchar,

ENUM 類型是很是快和緊湊的。在實際上,其保存的是 TINYINT,但其外表上顯示爲字符串。這樣一來,用這個字段來作一些選項列表變得至關的完美。

若是你有一個字段,好比「性別」,「國家」,「民族」,「狀態」或「部門」,你知道這些字段的取值是有限並且固定的,那麼,你應該使用 ENUM 而不是 VARCHAR。

MySQL也有一個「建議」(見第十條)告訴你怎麼去從新組織你的表結構。當你有一個 VARCHAR 字段時,這個建議會告訴你把其改爲 ENUM 類型。使用 PROCEDURE ANALYSE() 你能夠獲得相關的建議。

 

9、儘量使用not null

空值('')是不佔用空間的
NULL值是未知的,且佔用空間,不走索引,DBA建議建表的時候最好設置字段是NOT NULL 來避免這種低效率的事情的發生。
注意:
count()統計某列的記錄數的時候,若是採用的NULL值,會別系統自動忽略掉,可是空值是會進行統計到其中的。
對於timestamp數據類型,若是往這個數據類型插入的列插入NULL值,則出現的值是當前系統時間。插入空值,則會出現 '0000-00-00 00:00:00'

 10、IP地址 地址存成 UNSIGNED INT

11、固定長度的表會更快

若是表中全部的字段都時固定長度,則整個表會被認爲是static或者fixed-length 例如,表中沒有以下類型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一個這些字段,那麼這個表就不是「固定長度靜態表」了

12、垂直分割

就是一個大表切割成多個小表,能夠下降表的複雜度和字段的數目,從而達到優化

實例1:在user表中有一個字段是家庭地址等啊,在這個表中除了我的信息除外,並不常讀取和改寫這個字段,何不吧他放倒另一張表中,這樣會提升 表的性能

實例2:這個表中有一個是last——login的字段,每次登陸完畢都會更新,可是每次更新時都會吧表的查詢緩存清空,因此能夠吧這個字段放倒另一個表中,這樣就不會影響你對username等字段的頻繁查詢,由於查詢緩存會提升性能。查詢緩存保留了返回客戶端數據的完整結果,當緩存被命中時,服務器會立刻返回保存的結果,而且跳過解析,優化和執行的步驟,緩存也須要開銷,只有在節省的資源大於開銷的時候,緩存纔會真正的油效率,這和服務器的負載有關

十3、拆分大的delete和insert語句

由於會鎖表,會形成web crash

十4、越小的列越快

若是一個表只會有幾列罷了(好比說字典表,配置表),那麼,咱們就沒有理由使用 INT 來作主鍵,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 會更經濟一些。若是你不須要記錄時間,使用 DATE 要比 DATETIME 好得多。

十5、選擇正確的搜索引擎:

在 MySQL 中有兩個存儲引擎 MyISAM 和 InnoDB,每一個引擎都有利有弊。酷殼之前文章《MySQL: InnoDB 仍是 MyISAM?》討論和這個事情。

MyISAM 適合於一些須要大量查詢的應用,但其對於有大量寫操做並非很好。甚至你只是須要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都沒法操做直到讀操做完成。另外,MyISAM 對於 SELECT COUNT(*) 這類的計算是超快無比的。

InnoDB 的趨勢會是一個很是複雜的存儲引擎,對於一些小的應用,它會比 MyISAM 還慢。他是它支持「行鎖」 ,因而在寫操做比較多的時候,會更優秀。而且,他還支持更多的高級應用,好比:事務。

16. 當心「永久連接」

「永久連接」的目的是用來減小從新建立MySQL連接的次數。當一個連接被建立了,它會永遠處在鏈接的狀態,就算是數據庫操做已經結束了。並且,自從咱們的Apache開始重用它的子進程後——也就是說,下一次的HTTP請求會重用Apache的子進程,並重用相同的 MySQL 連接。

在理論上來講,這聽起來很是的不錯。可是從我的經驗(也是大多數人的)上來講,這個功能製造出來的麻煩事更多。由於,你只有有限的連接數,內存問題,文件句柄數,等等。

並且,Apache 運行在極端並行的環境中,會建立不少不少的了進程。這就是爲何這種「永久連接」的機制工做地很差的緣由。在你決定要使用「永久連接」以前,你須要好好地考慮一下你的整個系統的架構。

相關文章
相關標籤/搜索