SQL優(yōu)化
1.字段加索引。這個(gè)是大家都能想到的,但不得不說(shuō),加索引也是有技巧的,對(duì)于一些區(qū)分不是很大的情況來(lái)說(shuō),例如一個(gè)字段表示刪除與否的狀態(tài)只有0,1兩種值的情況下,這個(gè)字段就不要加索引了。意義不大。同時(shí),如果某張表里有排序字段的話,而且出現(xiàn)的頻率比較高的,例如通過(guò)符合索引來(lái)加字段。例如(field_name,create_time),經(jīng)常需要這樣查詢where field = field_name order create_time。當(dāng)然,復(fù)合索引也遵循前綴的原則,當(dāng)我們只是需要where field = field_name的時(shí)候,查詢也會(huì)走索引。
2.使用IN查詢時(shí)里面的值不應(yīng)該過(guò)多。MySQL對(duì)于IN做了相應(yīng)的優(yōu)化,即將IN中的常量全部存儲(chǔ)在一個(gè)數(shù)組里面,而且這個(gè)數(shù)組是排好序的。但是如果數(shù)值較多,產(chǎn)生的消耗也是比較大的。再例如:select id from t where num in(1,2,3) 對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in 。
3.在查詢的過(guò)程中如果不需要查詢出全部字段,盡量不要使用select 查詢。MySQL在查詢數(shù)據(jù)的時(shí)候,需要先把數(shù)據(jù)先拿出來(lái)然后再按照條件來(lái)篩選的。如果用查詢的話,就需要把整條記錄都拿出,增加了很多不必要的消耗(cpu、io、內(nèi)存、網(wǎng)絡(luò)帶寬);增加了使用覆蓋索引的可能性。
4.當(dāng)需要拿出一條數(shù)據(jù)時(shí),在sql結(jié)尾處最好加上limit 1。
5.模糊查詢的時(shí)候進(jìn)行用右模糊的方式。例如select field_name from table_name like field_name like 'xxx%'。這樣做的好處就是在查詢的時(shí)候會(huì)走索引,減少查詢時(shí)間。
6.連表查詢的時(shí)候盡量使用inner join,避免left join;被驅(qū)動(dòng)表的索引字段作為on的限制字段以此合理利用索引。參與聯(lián)合查詢的表至少為2張表,一般都存在大小之分。如果連接方式是inner join,在沒(méi)有其他過(guò)濾條件的情況下MySQL會(huì)自動(dòng)選擇小表作為驅(qū)動(dòng)表,但是left join在驅(qū)動(dòng)表的選擇上遵循的是左邊驅(qū)動(dòng)右邊的原則,即left join左邊的表名為驅(qū)動(dòng)表。
7.查詢的判斷條件中盡量的不要使用!=,not in或者是判斷null等情況。這些情況會(huì)導(dǎo)致查詢的效率變慢。
8.合理的利用分頁(yè)方式來(lái)提高分頁(yè)效率。例如select id,name from product limit 800000, 20。這條sql語(yǔ)句在隨著表的增大的過(guò)程中查詢會(huì)變得越來(lái)越慢。這種情況我們可以取前一頁(yè)的最大行數(shù)的id,然后根據(jù)這個(gè)最大的id來(lái)限制下一頁(yè)的起點(diǎn)。例如select id,name from product where id > 800000 limit 20。
9.如果限制條件中其他字段沒(méi)有索引,盡量少用or。or條件中如果有其他字段沒(méi)有索引的話,容易使得mysql在查詢的時(shí)候不走索引。大多時(shí)候都是用union all來(lái)代替or。
10.where字句中避免對(duì)字段進(jìn)行表達(dá)式操作。例如select user_name from user where age*2=30。對(duì)字段進(jìn)行算數(shù)操作會(huì)使其不走索引,所以這種情況應(yīng)該改成select user_name from user where age=15。
11.必要是強(qiáng)制使用force index讓查詢走索引。有時(shí)候MySQL的優(yōu)化器會(huì)走它認(rèn)為的合理的索引,但那時(shí)候可能不是我們想要的,所以有時(shí)候要使用強(qiáng)制所以的命令。
12.連表時(shí)盡量使用inner join。參與聯(lián)合查詢的表至少為2張表,一般都存在大小之分。如果連接方式是inner join,在沒(méi)有其他過(guò)濾條件的情況下MySQL會(huì)自動(dòng)選擇小表作為驅(qū)動(dòng)表。
SQL檢驗(yàn)
1.使用Explain來(lái)查看自己的sql語(yǔ)句使用索引的情況。如果是在命令行模式下的話,則是explain select.........的形式來(lái)查看。如果是用的Navicat這樣的sql工具的話,也可以在查詢的時(shí)候直接按解釋,也會(huì)出現(xiàn)sql索引使用的情況。形如下面:
其主要關(guān)鍵的幾個(gè)字段的意思如下:
1. type列,連接類型。一個(gè)好的sql語(yǔ)句至少要達(dá)到range級(jí)別。杜絕出現(xiàn)all級(jí)別
2. key列,使用到的索引名。如果沒(méi)有選擇索引,值是NULL??梢圆扇?qiáng)制索引方式
3. key_len列,索引長(zhǎng)度
4. rows列,掃描行數(shù)。該值是個(gè)預(yù)估值
5. extra列,詳細(xì)說(shuō)明。注意常見(jiàn)的不太友好的值有:Using filesort, Using temporary
當(dāng)然的,mysql還有其他方面的優(yōu)化。如果你真的想要深入對(duì)mysql的理解的話,也可以買(mǎi)一些書(shū)籍來(lái)看,深入mysql才能真正知道如何優(yōu)化最好。
2.通過(guò)慢查詢?nèi)罩緛?lái)定位查詢時(shí)間久的sql語(yǔ)句。執(zhí)行以下命令時(shí),可以查詢當(dāng)前的慢查詢的設(shè)置時(shí)間,默認(rèn)是10s。
show variables like 'long_query_time'
修改慢查詢時(shí)間,以下命令是設(shè)置慢查詢時(shí)間為2s。
set long_query_time=2
然后我們?cè)试Ssql語(yǔ)句,如果sql語(yǔ)句時(shí)間超過(guò)2s的話,就會(huì)被記錄。相應(yīng)的,記錄的位置我們可以參考MySQL的my.ini文件里的datadir這個(gè)參數(shù)的目錄,進(jìn)去相應(yīng)的目錄之后,我們可以看到一個(gè)slow.log結(jié)尾的文件,里面記錄的就是我們運(yùn)行的超過(guò)2s的mysql的查詢記錄。