mysql優(yōu)化-原理

原因:

性能低亡呵、執(zhí)行時間太長絮供、等待時間太長、SQL語句欠佳(連接查詢)帆赢、索引失效小压、服務(wù)器參數(shù)設(shè)置不合理(緩沖、線程數(shù))

SQL解析過程

編寫過程:
selectdinstinct..from..join..on..where..groupby...having..orderby..limit..

解析過程:
from..on..join..where..groupby....having...selectdinstinct..orderbylimit...

索引

主要就是在優(yōu)化索引
索引:相當(dāng)于書的目錄
索引:index是幫助MYSQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)椰于。索引是數(shù)據(jù)結(jié)構(gòu)(樹:B樹(默認(rèn))怠益、Hash樹...)

索引的弊端:
1.索引本身很大,可以存放在內(nèi)存/硬盤(通常為硬盤)
2.索引不是所有情況均適用:a.少量數(shù)據(jù)b.頻繁更新的字段c.很少使用的字段
3.索引會降低增刪改的效率(增刪改查)

索引的優(yōu)勢:
1.提高查詢效率(降低IO使用率)
2.降低CPU使用率(...orderbyagedesc,因?yàn)锽樹索引本身就是一個好排序的結(jié)構(gòu)瘾婿,因此在排序時可以直接使用)

https://www.cnblogs.com/annsshadow/p/5037667.html

分類:
主鍵索引:不能重復(fù)蜻牢。id不能是null
唯一索引:不能重復(fù)。id可以是null
單值索引:單列偏陪,age;一個表可以多個單值索引,name抢呆。
復(fù)合索引:多個列構(gòu)成的索引(相當(dāng)于二級目錄:z:zhao)(name,age)(a,b,c,d,...,n)
創(chuàng)建索引:
方式一:create索引類型索引名on表(字段)
單值:
createindexdept_indexontb(dept);
唯一:
createuniqueindexname_indexontb(name);
復(fù)合索引
createindexdept_name_indexontb(dept,name);

方式二:altertable表名索引類型索引名(字段)
單值:
altertabletbaddindexdept_index(dept);
唯一:
altertabletbadduniqueindexname_index(name);
復(fù)合索引
altertabletbaddindexdept_name_index(dept,name);

注意:如果一個字段是primarykey,則改字段默認(rèn)就是主鍵索引

刪除索引:
dropindex索引名on表名;
dropindexname_indexontb;

查詢索引:
showindexfrom表名;
showindexfrom表名\G

SQL性能問題

a.分析SQL的執(zhí)行計(jì)劃:explain笛谦,可以模擬SQL優(yōu)化器執(zhí)行SQL語句抱虐,從而讓開發(fā)人員知道自己編寫的SQL狀況
b.MySQL查詢優(yōu)化其會干擾我們的優(yōu)化

https://dev.mysql.com/doc/refman/5.5/en/optimization.html

查詢執(zhí)行計(jì)劃:

explain+SQL語句
explainselect*fromtb;

id:編號
select_type:查詢類型
table:表
type:類型
possible_keys:預(yù)測用到的索引
key:實(shí)際使用的索引
key_len:實(shí)際使用索引的長度
ref:表之間的引用
rows:通過索引查詢到的數(shù)據(jù)量
Extra:額外的信息

準(zhǔn)備數(shù)據(jù):
createtablecourse
(
cidint(3),
cnamevarchar(20),
tidint(3)
);
createtableteacher
(
tidint(3),
tnamevarchar(20),
tcidint(3)
);

createtableteacherCard
(
tcidint(3),
tcdescvarchar(200)
);

insertintocoursevalues(1,'java',1);
insertintocoursevalues(2,'html',1);
insertintocoursevalues(3,'sql',2);
insertintocoursevalues(4,'web',3);

insertintoteachervalues(1,'tz',1);
insertintoteachervalues(2,'tw',2);
insertintoteachervalues(3,'tl',3);

insertintoteacherCardvalues(1,'tzdesc');
insertintoteacherCardvalues(2,'twdesc');
insertintoteacherCardvalues(3,'tldesc');

查詢課程編號為2或教師證編號為3的老師信息
explain+sql:

(1)id:

id值相同,從上往下順序執(zhí)行饥脑。
t3-tc3-c4
tc3--c4-t6
表的執(zhí)行順序因數(shù)量的個數(shù)改變而改變的原因:笛卡兒積
abc
432=23=64=24
34=122=24
數(shù)據(jù)小的表優(yōu)先查詢恳邀;

id值不同:id值越大越優(yōu)先查詢
(本質(zhì):在嵌套子查詢時,先查內(nèi)層再查外層)
查詢教授SQL課程的老師的描述(desc)
explainselecttc.tcdescfromteacherCardtc,coursec,teachertwherec.tid=t.tid
andt.tcid=tc.tcidandc.cname='sql';

將以上多表查詢轉(zhuǎn)為子查詢形式:

explainselecttc.tcdescfromteacherCardtcwheretc.tcid=
(selectt.tcidfromteachertwheret.tid=
(selectc.tidfromcoursecwherec.cname='sql')
);

子查詢+多表:
explainselectt.tname,tc.tcdescfromteachert,teacherCardtcwheret.tcid=tc.tcid
andt.tid=(selectc.tidfromcoursecwherecname='sql');

id值有相同好啰,又有不同:id值越大越優(yōu)先轩娶;id值相同儿奶,從上往下順序執(zhí)行

(2)select_type:查詢類型

PRIMARY:包含子查詢SQL中的主查詢(最外層)
SUBQUERY:包含子查詢SQL中的子查詢(非最外層)
simple:簡單查詢(不包含子查詢框往、union)
derived:衍生查詢(使用到了臨時表)
a.在from子查詢中只有一張表
explainselectcr.cnamefrom(select*fromcoursewheretidin(1,2))cr;

b.在from子查詢中,如果有table1uniontable2闯捎,則table1就是derived,table2就是union
explainselectcr.cnamefrom(selectfromcoursewheretid=1unionselectfromcoursewheretid=2)cr;
union:上例
unionresult:告知開發(fā)人員椰弊,那些表之間存在union查詢

system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL

(3)type:索引類型许溅、類型

system>const>eq_ref>ref>range>index>all,要對type進(jìn)行優(yōu)化的前提:有索引
其中:system,const只是理想情況秉版;實(shí)際能達(dá)到ref>range
system(忽略):只有一條數(shù)據(jù)的系統(tǒng)表贤重;或衍生表只有一條數(shù)據(jù)的主查詢

createtabletest01
(
tidint(3),
tnamevarchar(20)
);

insertintotest01values(1,'a');
commit;
增加索引
altertabletest01addconstrainttid_pkprimarykey(tid);
explainselectfrom(selectfromtest01)twheretid=1;

const:僅僅能查到一條數(shù)據(jù)的SQL,用于Primarykey或unique索引(類型與索引類型有關(guān))
explainselecttidfromtest01wheretid=1;
altertabletest01dropprimarykey;
createindextest01_indexontest01(tid);

eq_ref:唯一性索引:對于每個索引鍵的查詢,返回匹配唯一行數(shù)據(jù)(有且只有1個清焕,不能多并蝗、不能0)
select...from..wherename=....常見于唯一索引和主鍵索引。

altertableteacherCardaddconstraintpk_tcidprimarykey(tcid);
altertableteacheraddconstraintuk_tciduniqueindex(tcid);

explainselectt.tcidfromteachert,teacherCardtcwheret.tcid=tc.tcid;

以上SQL秸妥,用到的索引是t.tcid,即teacher表中的tcid字段滚停;
如果teacher表的數(shù)據(jù)個數(shù)和連接查詢的數(shù)據(jù)個數(shù)一致(都是3條數(shù)據(jù)),則有可能滿足eq_ref級別粥惧;否則無法滿足键畴。

ref:非唯一性索引,對于每個索引鍵的查詢突雪,返回匹配的所有行(0起惕,多)
準(zhǔn)備數(shù)據(jù):
insertintoteachervalues(4,'tz',4);
insertintoteacherCardvalues(4,'tz222');

測試:
altertableteacheraddindexindex_name(tname);
explainselect*fromteacherwheretname='tz';

range:檢索指定范圍的行,where后面是一個范圍查詢(between,><>=,特殊:in有時候會失效,從而轉(zhuǎn)為無索引all)
altertableteacheraddindextid_index(tid);
explainselectt.fromteachertwheret.tidin(1,2);
explainselectt.
fromteachertwheret.tid<3;

index:查詢?nèi)克饕袛?shù)據(jù)
explainselecttidfromteacher;--tid是索引咏删,只需要掃描索引表惹想,不需要所有表中的所有數(shù)據(jù)

all:查詢?nèi)勘碇械臄?shù)據(jù)
explainselectcidfromcourse;--cid不是索引,需要全表所有督函,即需要所有表中的所有數(shù)據(jù)

system/const:結(jié)果只有一條數(shù)據(jù)
eq_ref:結(jié)果多條勺馆;但是每條數(shù)據(jù)是唯一的;
ref:結(jié)果多條侨核;但是每條數(shù)據(jù)是是0或多條草穆;

(4)possible_keys:可能用到的索引,是一種預(yù)測搓译,不準(zhǔn)悲柱。

altertablecourseaddindexcname_index(cname);

explainselectt.tname,tc.tcdescfromteachert,teacherCardtc
wheret.tcid=tc.tcid
andt.tid=(selectc.tidfromcoursecwherecname='sql');

如果possible_key/key是NULL,則說明沒用索引

explainselecttc.tcdescfromteacherCardtc,coursec,teachertwherec.tid=t.tid
andt.tcid=tc.tcidandc.cname='sql';

(5)key:實(shí)際使用到的索引

(6)key_len:索引的長度;

作用:用于判斷復(fù)合索引是否被完全使用(a,b,c)些己。
createtabletest_kl
(
namechar(20)notnulldefault''
);
altertabletest_kladdindexindex_name(name);
explainselect*fromtest_klwherename='';--key_len:60
在utf8:1個字符站3個字節(jié)

altertabletest_kladdcolumnname1char(20);--name1可以為null

altertabletest_kladdindexindex_name1(name1);
explainselect*fromtest_klwherename1='';
--如果索引字段可以為Null,則會使用1個字節(jié)用于標(biāo)識豌鸡。

dropindexindex_nameontest_kl;
dropindexindex_name1ontest_kl;

增加一個復(fù)合索引
altertabletest_kladdindexname_name1_index(name,name1);

explainselectfromtest_klwherename1='';--121
explainselect
fromtest_klwherename='';--60

varchar(20)
altertabletest_kladdcolumnname2varchar(20);--可以為Null
altertabletest_kladdindexname2_index(name2);

explainselectfromtest_klwherename2='';--63
20
3=60+1(null)+2(用2個字節(jié)標(biāo)識可變長度)=63

utf8:1個字符3個字節(jié)
gbk:1個字符2個字節(jié)
latin:1個字符1個字節(jié)

(7)ref:注意與type中的ref值區(qū)分。

作用:指明當(dāng)前表所參照的字段段标。
select....wherea.c=b.x;(其中b.x可以是常量涯冠,const)

altertablecourseaddindextid_index(tid);

explainselect*fromcoursec,teachertwherec.tid=t.tidandt.tname='tw';

(8)rows:被索引優(yōu)化查詢的數(shù)據(jù)個數(shù)(實(shí)際通過索引而查詢到的數(shù)據(jù)個數(shù))

explainselect*fromcoursec,teachertwherec.tid=t.tid
andt.tname='tz';

(9)Extra:

(i).usingfilesort:性能消耗大;需要“額外”的一次排序(查詢)逼庞。常見于orderby語句中蛇更。
排序:先查詢

10個人根據(jù)年齡排序。

createtabletest02
(
a1char(3),
a2char(3),
a3char(3),
indexidx_a1(a1),
indexidx_a2(a2),
indexidx_a3(a3)
);

explainselect*fromtest02wherea1=''orderbya1;

a1:姓名a2:年齡

explainselect*fromtest02wherea1=''orderbya2;--usingfilesort
小結(jié):對于單索引,如果排序和查找是同一個字段派任,則不會出現(xiàn)usingfilesort砸逊;如果排序和查找不是同一個字段,則會出現(xiàn)usingfilesort掌逛;
避免:where哪些字段师逸,就orderby那些字段2

復(fù)合索引:不能跨列(最佳左前綴)
dropindexidx_a1ontest02;
dropindexidx_a2ontest02;
dropindexidx_a3ontest02;

altertabletest02addindexidx_a1_a2_a3(a1,a2,a3);
explainselectfromtest02wherea1=''orderbya3;--usingfilesort
explainselect
fromtest02wherea2=''orderbya3;--usingfilesort
explainselectfromtest02wherea1=''orderbya2;
explainselect
fromtest02wherea2=''orderbya1;--usingfilesort
小結(jié):避免:where和orderby按照復(fù)合索引的順序使用,不要跨列或無序使用豆混。

(ii).usingtemporary:性能損耗大篓像,用到了臨時表。一般出現(xiàn)在groupby語句中皿伺。
explainselecta1fromtest02wherea1in('1','2','3')groupbya1;
explainselecta1fromtest02wherea1in('1','2','3')groupbya2;--usingtemporary
避免:查詢那些列遗淳,就根據(jù)那些列g(shù)roupby.

(iii).usingindex:性能提升;索引覆蓋(覆蓋索引)。原因:不讀取原文件心傀,只從索引文件中獲取數(shù)據(jù)(不需要回表查詢)
只要使用到的列全部都在索引中屈暗,就是索引覆蓋usingindex

例如:test02表中有一個復(fù)合索引(a1,a2,a3)
explainselecta1,a2fromtest02wherea1=''ora2='';--usingindex

dropindexidx_a1_a2_a3ontest02;

altertabletest02addindexidx_a1_a2(a1,a2);
explainselecta1,a3fromtest02wherea1=''ora3='';

如果用到了索引覆蓋(usingindex時),會對possible_keys和key造成影響:
a.如果沒有where脂男,則索引只出現(xiàn)在key中养叛;
b.如果有where,則索引出現(xiàn)在key和possible_keys中宰翅。

explainselecta1,a2fromtest02wherea1=''ora2='';
explainselecta1,a2fromtest02;

(iii).usingwhere(需要回表查詢)
假設(shè)age是索引列
但查詢語句selectage,namefrom...whereage=...,此語句中必須回原表查Name弃甥,因此會顯示usingwhere.

explainselecta1,a3fromtest02wherea3='';--a3需要回原表查詢

(iv).impossiblewhere:where子句永遠(yuǎn)為false
explainselect*fromtest02wherea1='x'anda1='y';

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市汁讼,隨后出現(xiàn)的幾起案子淆攻,更是在濱河造成了極大的恐慌,老刑警劉巖嘿架,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓶珊,死亡現(xiàn)場離奇詭異,居然都是意外死亡耸彪,警方通過查閱死者的電腦和手機(jī)伞芹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝉娜,“玉大人唱较,你說我怎么就攤上這事≌俅ǎ” “怎么了南缓?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荧呐。 經(jīng)常有香客問我汉形,道長纸镊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任获雕,我火速辦了婚禮薄腻,結(jié)果婚禮上收捣,老公的妹妹穿的比我還像新娘届案。我一直安慰自己,他們只是感情好罢艾,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布楣颠。 她就那樣靜靜地躺著,像睡著了一般咐蚯。 火紅的嫁衣襯著肌膚如雪童漩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天春锋,我揣著相機(jī)與錄音矫膨,去河邊找鬼。 笑死期奔,一個胖子當(dāng)著我的面吹牛侧馅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播呐萌,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼馁痴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肺孤?” 一聲冷哼從身側(cè)響起罗晕,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赠堵,沒想到半個月后小渊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茫叭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年粤铭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杂靶。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡梆惯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吗垮,到底是詐尸還是另有隱情垛吗,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布烁登,位于F島的核電站怯屉,受9級特大地震影響蔚舀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锨络,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一赌躺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧羡儿,春花似錦礼患、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至虏冻,卻和暖如春肤粱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厨相。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工领曼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛮穿。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓庶骄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绪撵。 傳聞我的和親對象是個殘疾皇子瓢姻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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