MySQL性能優(yōu)化及分析

一毁欣、mysql性能優(yōu)化
1.查詢緩存
當有很多相同的查詢被執(zhí)行了多次的時候,這些查詢結(jié)果會被放到一個緩存中岳掐,這樣凭疮,后續(xù)的相同的查詢就不用操作表而直接訪問緩存結(jié)果了。

// 查詢緩存不開啟 
$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'"); 

上面兩條SQL語句的差別就是 CURDATE() 串述,MySQL的查詢緩存對這個函數(shù)不起作用执解。所以,像 NOW() 和 RAND() 或是其它的諸如此類的SQL函數(shù)都不會開啟查詢緩存纲酗,因為這些函數(shù)的返回是會不定的易變的衰腌。所以,你所需要的就是用一個變量來代替MySQL的函數(shù)觅赊,從而 開啟緩存右蕊。
2.當只獲取一行數(shù)據(jù)時用 Limit 1
3.為搜索字段建索引
索引分類:
a.普通索引----這是最基本的索引,它沒有任何限制吮螺,MyIASM中默認的BTREE類型的索引饶囚,也是我們大多數(shù)情況下用到的索引。

CREATE INDEX index_name ON table(column(length))
索引

b.唯一索引----與普通索引類似规脸,不同的就是:索引列的值必須唯一坯约,但允許有空值(注意和主鍵不同)。

CREATE UNIQUE INDEX indexName ON table(column(length))

c.全文索引(FULLTEXT)----FULLTEXT索引僅可用于 MyISAM 表莫鸭,他們可以從CHAR闹丐、VARCHAR或TEXT列中作為CREATE TABLE語句的一部分被創(chuàng)建,或是隨后使用ALTER TABLE 或CREATE INDEX被添加被因。

–創(chuàng)建表的適合添加全文索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
FULLTEXT (content)
);
–修改表結(jié)構(gòu)添加全文索引
ALTER TABLE article ADD FULLTEXT index_content(content)
–直接創(chuàng)建索引
CREATE FULLTEXT INDEX index_content ON article(content)

但是對于較大的數(shù)據(jù)來說往一個用于FULLTEXT的表中插入數(shù)據(jù)非常消耗時間和硬盤空間卿拴。
d.單列索引衫仑、多列索引----多個單列索引與單個多列索引的查詢效果不同,因為執(zhí)行查詢時堕花,MySQL只能使用一個索引文狱,會從多個索引中選擇一個限制最為嚴格的索引。
e.組合索引----例如上表中針對title和time建立一個組合索引

ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))

4.使用 ENUM 而不是 VARCHAR
ENUM 類型是非吃低欤快和緊湊的瞄崇。在實際上,其保存的是 TINYINT壕曼,但其外表上顯示為字符串苏研。這樣一來,用這個字段來做一些選項列表變得相當?shù)耐昝馈?br> 5.盡可能的使用 NOT NULL
NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.
NULL需要額外的空間
6.字段長度固定
固定長度的表會提高性能腮郊,因為MySQL搜尋得會更快一些摹蘑,因為這些固定的長度是很容易計算下一個數(shù)據(jù)的偏移量的,所以讀取的自然也會很快轧飞。而如果字段不是定長的衅鹿,那么,每一次要找下一條的話过咬,需要程序找到主鍵大渤。
7.避免 select *、count()
8.應盡量避免在 where 子句中使用!=或<>操作符掸绞,否則將引擎放棄使用索引而進行全表掃描兼犯。
9.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描集漾,如:

select id from t where num=10 or num=20 

可以這樣查詢:

select id from t where num=10 
union all 
select id from t where num=20 

10.in 和 not in 也要慎用切黔,否則會導致全表掃描。

select id from t where num in(1,2,3) 

對于連續(xù)的數(shù)值具篇,能用 between 就不要用 in 了:

select id from t where num between 1 and 3 

11.應盡量避免在 where 子句中對字段進行表達式操作纬霞,這將導致引擎放棄使用索引而進行全表掃描。

select id from t where num/2=100 

應改為:

select id from t where num=100*2 

12.很多時候用 exists 代替 in 是一個好的選擇驱显。

select num from a where num in(select num from b) 

用下面的語句替換:

select num from a where exists(select 1 from b where num=a.num) 

13.并不是所有索引對查詢都有效诗芜,SQL是根據(jù)表中數(shù)據(jù)來進行查詢優(yōu)化的,當索引列有大量數(shù)據(jù)重復時埃疫,SQL查詢可能不會去利用索引伏恐,如一表中有字段sex,male栓霜、female幾乎各一半翠桦,那么即使在sex上建了索引也對查詢效率起不了作用。
14.臨時表并不是不可使用,適當?shù)厥褂盟鼈兛梢允鼓承├谈行眨绱陨危斝枰貜鸵么笮捅砘虺S帽碇械哪硞€數(shù)據(jù)集時。但是斗幼,對于一次性事件澎蛛,最好使用導出表。
15.拆分大的 DELETE 或 INSERT 語句蜕窿。因為這兩個操作是會鎖表的谋逻,表一鎖住了,別的操作都進不來了桐经。
二斤贰、mysql優(yōu)化分析
1.使用explain語句去查看分析結(jié)果
explain命令的使用十分簡單,只需要"explain + sql語句"即可

explain select * from test1 where id=1;

會出現(xiàn):id selecttype table type possible_keys key key_len ref rows extra各列次询。


explain
id:SELECT識別符。這是SELECT的查詢序列號瓷叫;
select_type:查詢類型屯吊,主要有PRIMARY(子查詢中最外層查詢)、SUBQUERY(子查詢內(nèi)層第一個SELECT)摹菠、UNION(UNION語句中第二個SELECT開始后面所有SELECT)盒卸、SIMPLE(除了子查詢或者union之外的其他查詢);
table:所訪問的數(shù)據(jù)庫表明次氨;
type:對表的訪問方式蔽介,包括以下類型all(全表掃描),index(全索引掃描)煮寡,rang(索引范圍掃描)虹蓄,ref(join語句中被驅(qū)動表索引引用查詢),eq_ref(通過主鍵或唯一索引訪問幸撕,最多只會有一條結(jié)果)薇组,const(讀常量,只需讀一次)坐儿,system(系統(tǒng)表律胀。表中只有一條數(shù)據(jù)),null(速度最快)貌矿。
possible_keys:查詢可能使用到的索引炭菌;
key:最后選用的索引;
key_len:使用索引的最大長度逛漫;
ref:列出某個表的某個字段過濾黑低;
rows:估算出的結(jié)果行數(shù);
extra:查詢細節(jié)信息酌毡,可能是以下值:distinct投储、using filesort(order by操作)第练、using index(所查數(shù)據(jù)只需要在index中即可獲取)玛荞、using temporary(使用臨時表)娇掏、using where(如果包含where,且不是僅通過索引即可獲取內(nèi)容勋眯,就會包含此信息)婴梧。

2.Profiling 的使用
mysql除了提供explain命令用于查看命令執(zhí)行計劃外,還提供了profiling工具用于查看語句查詢過程中的資源消耗情況客蹋。首先我們要使用以下命令開啟Profiling功能:

set profiling = 1;

然后執(zhí)行一條查詢命令:

select * from stu;
查詢結(jié)果

在開啟了Query Profiler功能之后,MySQL就會自動記錄所有執(zhí)行的Query的profile信息了塞蹭。 然后我們通過以下命令獲取系統(tǒng)中保存的所有 Query 的 profile 概要信息:

show profiles;
profile記錄

然后我們可以通過以下命令查看具體的某一次查詢的profile信息:

show profile cpu, block io for query 1;
profile

該profile顯示了每一步操作的耗時以及cpu和Block IO的消耗,這樣我們就可以更有針對性的優(yōu)化查詢語句了讶坯。

3.查看慢查詢
我們可以用以下命令查看慢查詢次數(shù):

show status like 'slow_queries';

使用該命令只能查看慢查詢次數(shù)番电,但是我們沒有辦法知道是哪些查詢產(chǎn)生了慢查詢,如果想要知道是哪些查詢導致的慢查詢辆琅,那么我們必須修改mysql的配置文件漱办。打開mysql的配置文件(windows系統(tǒng)是my.ini,linux系統(tǒng)是my.cnf),在[mysqld]下面加上以下代碼:

log-slow-queries=mysql_slow.log
long_query_time=1

此時我們在mysql中運行以下命令婉烟,可以看到slow_query_log是ON狀態(tài)娩井,log_file也是我們指定的文件:

mysql> show variables like 'slow_query%'; 
+---------------------+------------------------------+
| Variable_name       | Value                        |
+---------------------+------------------------------+
| slow_query_log      | ON                           |
| slow_query_log_file | mysql_slow.log |
+---------------------+------------------------------+
2 rows in set (0.00 sec)

運行以下命令我們可以看到我們設定的慢查詢時間也生效了,此時只要查詢時間大于1s似袁,查詢語句都將存入日志文件洞辣。

mysql> show variables like 'long_query_time'; 
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
1 row in set (0.00 sec)

現(xiàn)在我們運行一個查詢時間超過1s的查詢語句:

mysql> select * from emp where empno=413345;
+--------+--------+----------+-----+------------+---------+--------+--------+
| empno  | ename  | job      | mgr | hiredate   | sal     | comm   | deptno |
+--------+--------+----------+-----+------------+---------+--------+--------+
| 413345 | vvOHUB | SALESMAN |   1 | 2014-10-26 | 2000.00 | 400.00 |     11 |
+--------+--------+----------+-----+------------+---------+--------+--------+
1 row in set (6.55 sec)

然后查看mysql安裝目錄下的data目錄,該目錄會產(chǎn)生一個慢查詢?nèi)罩疚募簃ysql_slow.log昙衅,在該日志文件中扬霜,我們可以知道慢查詢產(chǎn)生的時間,最終產(chǎn)生了幾行結(jié)果而涉,測試了幾行結(jié)果畜挥,以及運行語句是什么。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婴谱,一起剝皮案震驚了整個濱河市蟹但,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谭羔,老刑警劉巖华糖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瘟裸,居然都是意外死亡客叉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兼搏,“玉大人卵慰,你說我怎么就攤上這事》鹕耄” “怎么了裳朋?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吓著。 經(jīng)常有香客問我鲤嫡,道長,這世上最難降的妖魔是什么绑莺? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任暖眼,我火速辦了婚禮,結(jié)果婚禮上纺裁,老公的妹妹穿的比我還像新娘诫肠。我一直安慰自己,他們只是感情好欺缘,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布栋豫。 她就那樣靜靜地躺著,像睡著了一般浪南。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漱受,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天络凿,我揣著相機與錄音,去河邊找鬼昂羡。 笑死絮记,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的虐先。 我是一名探鬼主播怨愤,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛹批!你這毒婦竟也來了撰洗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤腐芍,失蹤者是張志新(化名)和其女友劉穎差导,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猪勇,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡设褐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片助析。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡犀被,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出外冀,到底是詐尸還是另有隱情寡键,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布锥惋,位于F島的核電站昌腰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏膀跌。R本人自食惡果不足惜遭商,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捅伤。 院中可真熱鬧劫流,春花似錦、人聲如沸丛忆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熄诡。三九已至可很,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凰浮,已是汗流浹背我抠。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留袜茧,地道東北人菜拓。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像笛厦,于是被迫代替她去往敵國和親纳鼎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容