InnoDB在處理更新語(yǔ)句時(shí),先寫內(nèi)存再寫redo log,并不會(huì)立即將數(shù)據(jù)頁(yè)的更新落地到磁盤(WAL機(jī)制),這就會(huì)產(chǎn)生升內(nèi)存數(shù)據(jù)頁(yè)和磁盤數(shù)據(jù)頁(yè)的數(shù)據(jù)不一致的情況,這種數(shù)據(jù)不一致的數(shù)據(jù)頁(yè)稱為 臟頁(yè) ,當(dāng)臟頁(yè)寫入到磁盤(這個(gè)操作稱為flush)后,數(shù)據(jù)一致后稱為干凈頁(yè)。
創(chuàng)新互聯(lián)建站服務(wù)項(xiàng)目包括泗洪網(wǎng)站建設(shè)、泗洪網(wǎng)站制作、泗洪網(wǎng)頁(yè)制作以及泗洪網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,泗洪網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到泗洪省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
第3種是系統(tǒng)空閑不會(huì)有性能問題,第4種是要關(guān)閉了不考慮性能問題。第1和2的情況flush臟頁(yè)會(huì)產(chǎn)生系統(tǒng)性能問題。
此時(shí)整個(gè)系統(tǒng)不能再更新了,更新數(shù)會(huì)降為0,所以這種情況要盡量避免。
InnoDB緩沖池(buffer pool)中的內(nèi)存頁(yè)有三種狀態(tài):
當(dāng)一個(gè)SQL語(yǔ)句要淘汰的臟頁(yè)數(shù)量太多,會(huì)導(dǎo)致語(yǔ)句執(zhí)行的響應(yīng)時(shí)間顯著邊長(zhǎng)。
InnoDB為了避免出現(xiàn)上述兩種情況,需要有控制臟頁(yè)比例的策略,控制的主要參考因素就是:臟頁(yè)比例和redo log寫盤速度。
需要告訴InnoDB的磁盤讀寫能力(IOPS)讓引擎全力flush臟頁(yè),磁盤的IOPS可以通過fio工具測(cè)試。
如果 innodb_io_capacity 參數(shù)設(shè)置的不合理,比如遠(yuǎn)遠(yuǎn)低于磁盤實(shí)際的IOPS,InnoDB會(huì)認(rèn)為IO性能低,刷臟頁(yè)速度會(huì)很慢,甚至低于臟頁(yè)的生成速度,導(dǎo)致臟頁(yè)累計(jì)影響查詢和更新性能。
為了兼顧正常的業(yè)務(wù)請(qǐng)求,InnoDB引擎控制按照磁盤IOPS的百分比來(lái)刷臟頁(yè),具體流程如下:
臟頁(yè)比例計(jì)算:
Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total
SQL語(yǔ)句如下:
在準(zhǔn)備flush一個(gè)臟頁(yè)時(shí),如果相鄰的數(shù)據(jù)頁(yè)也是臟頁(yè),會(huì)把這個(gè)臟頁(yè)一起flush,而且對(duì)這個(gè)新的臟頁(yè)還可能有相鄰的臟頁(yè)導(dǎo)致連鎖flush。
InnoDB使用 innodb_flush_neighbors 參數(shù)控制這個(gè)行為,值為1會(huì)產(chǎn)生上述連鎖flush的情況,值為0則不會(huì)找相鄰頁(yè)。
找相鄰頁(yè)flush的機(jī)制雖然可以減少很多隨機(jī)IO,但會(huì)增加一次flush時(shí)間,導(dǎo)致flush時(shí)的SQL語(yǔ)句執(zhí)行時(shí)間變慢。
現(xiàn)在基本都使用的SSD這種IOPS比較高的硬盤,建議將 innodb_flush_neighbors 參數(shù)設(shè)為0,提高flush的速度。
flush會(huì)占用IO資源影響了正在執(zhí)行的SQL語(yǔ)句,本來(lái)正常情況下執(zhí)行很快的一條語(yǔ)句,突然耗時(shí)大大增加,造成業(yè)務(wù)抖動(dòng)。要盡量避免這種情況,需要合理的設(shè)置 innodb_io_capacity 的值,并且多關(guān)注臟頁(yè)比例,不要讓臟頁(yè)比例經(jīng)常接近75%。
【極客時(shí)間】 MySQL實(shí)戰(zhàn)45講:第12節(jié)
數(shù)據(jù)準(zhǔn)備:
學(xué)生表 Student:
科目表 Course
教師表 Teacher
成績(jī)表 SC
45題預(yù)覽:
題目
1.查詢" 01 "課程比" 02 "課程成績(jī)高的學(xué)生的信息及課程分?jǐn)?shù)
1.1 查詢同時(shí)存在" 01 "課程和" 02 "課程的情況
1.2 查詢存在" 01 "課程但可能不存在" 02 "課程的情況(不存在時(shí)顯示為 null ) 1.3 查詢不存在" 01 "課程但存在" 02 "課程的情況
2.查詢平均成績(jī)大于等于 60 分的同學(xué)的學(xué)生編號(hào)和學(xué)生姓名和平均成績(jī)
3.查詢?cè)?SC 表存在成績(jī)的學(xué)生信息
4.查詢所有同學(xué)的學(xué)生編號(hào)、學(xué)生姓名、選課總數(shù)、所有課程的總成績(jī)(沒成績(jī)的顯示為 null )
4.1 查有成績(jī)的學(xué)生信息
5.查詢「李」姓老師的數(shù)量
6.查詢學(xué)過「張三」老師授課的同學(xué)的信息
7.查詢沒有學(xué)全所有課程的同學(xué)的信息
8.查詢至少有一門課與學(xué)號(hào)為" 01 "的同學(xué)所學(xué)相同的同學(xué)的信息
9.查詢和" 01 "號(hào)的同學(xué)學(xué)習(xí)的課程 完全相同的其他同學(xué)的信息
10.查詢沒學(xué)過"張三"老師講授的任一門課程的學(xué)生姓名
11.查詢兩門及其以上不及格課程的同學(xué)的學(xué)號(hào),姓名及其平均成績(jī)
12.檢索" 01 "課程分?jǐn)?shù)小于 60,按分?jǐn)?shù)降序排列的學(xué)生信息
13.按平均成績(jī)從高到低顯示所有學(xué)生的所有課程的成績(jī)以及平均成績(jī)
14.查詢各科成績(jī)最高分、最低分和平均分: 以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格率,中等率,優(yōu)良率,優(yōu)秀率 及格為=60,中等為:70-80,優(yōu)良為:80-90,優(yōu)秀為:=90 要求輸出課程號(hào)和選修人數(shù),查詢結(jié)果按人數(shù)降序排列,若人數(shù)相同,按課程號(hào)升序排列
15.按各科成績(jī)進(jìn)行排序,并顯示排名, Score 重復(fù)時(shí)保留名次空缺 15.1 按各科成績(jī)進(jìn)行排序,并顯示排名, Score 重復(fù)時(shí)合并名次
16.查詢學(xué)生的總成績(jī),并進(jìn)行排名,總分重復(fù)時(shí)保留名次空缺 16.1 查詢學(xué)生的總成績(jī),并進(jìn)行排名,總分重復(fù)時(shí)不保留名次空缺
17.統(tǒng)計(jì)各科成績(jī)各分?jǐn)?shù)段人數(shù):課程編號(hào),課程名稱,[100-85],[85-70],[70-60],[60-0] 及所占百分比
18.查詢各科成績(jī)前三名的記錄
19.查詢每門課程被選修的學(xué)生數(shù)
20.查詢出只選修兩門課程的學(xué)生學(xué)號(hào)和姓名
21.查詢男生、女生人數(shù)
22.查詢名字中含有「風(fēng)」字的學(xué)生信息
23.查詢同名同性學(xué)生名單,并統(tǒng)計(jì)同名人數(shù)
24.查詢 1990 年出生的學(xué)生名單
25.查詢每門課程的平均成績(jī),結(jié)果按平均成績(jī)降序排列,平均成績(jī)相同時(shí),按課程編號(hào)升序排列
26.查詢平均成績(jī)大于等于 85 的所有學(xué)生的學(xué)號(hào)、姓名和平均成績(jī)
27.查詢課程名稱為「數(shù)學(xué)」,且分?jǐn)?shù)低于 60 的學(xué)生姓名和分?jǐn)?shù)
28.查詢所有學(xué)生的課程及分?jǐn)?shù)情況(存在學(xué)生沒成績(jī),沒選課的情況)
29.查詢?nèi)魏我婚T課程成績(jī)?cè)?70 分以上的姓名、課程名稱和分?jǐn)?shù)
30.查詢不及格的課程
31.查詢課程編號(hào)為 01 且課程成績(jī)?cè)?80 分以上的學(xué)生的學(xué)號(hào)和姓名
32.求每門課程的學(xué)生人數(shù)
33.假設(shè)成績(jī)不重復(fù),查詢選修「張三」老師所授課程的學(xué)生中,成績(jī)最高的學(xué)生信息及其成績(jī)
34.假設(shè)成績(jī)有重復(fù)的情況下,查詢選修「張三」老師所授課程的學(xué)生中,成績(jī)最高的學(xué)生信息及其成績(jī)
35.查詢不同課程成績(jī)相同的學(xué)生的學(xué)生編號(hào)、課程編號(hào)、學(xué)生成績(jī)
36.查詢每門功成績(jī)最好的前兩名
37.統(tǒng)計(jì)每門課程的學(xué)生選修人數(shù)(超過 5 人的課程才統(tǒng)計(jì))。
38.檢索至少選修兩門課程的學(xué)生學(xué)號(hào)
39.查詢選修了全部課程的學(xué)生信息
40.查詢各學(xué)生的年齡,只按年份來(lái)算
41.按照出生日期來(lái)算,當(dāng)前月日 出生年月的月日則,年齡減一
42.查詢本周過生日的學(xué)生
43.查詢下周過生日的學(xué)生
44.查詢本月過生日的學(xué)生
45.查詢下月過生日的學(xué)生
詳細(xì)
1.查詢" 01 "課程比" 02 "課程成績(jī)高的學(xué)生的信息及課程分?jǐn)?shù)
理清思路:
(1)學(xué)生信息和課程分?jǐn)?shù)分布對(duì)應(yīng)于student表和sc表
所以,我們需要把它們關(guān)聯(lián)起來(lái)
(2)需要比較同一學(xué)生的不同成績(jī),所以需要再關(guān)聯(lián)成績(jī)表sc
(3)利用where進(jìn)行篩選
1.1 查詢同時(shí)存在" 01 "課程和" 02 "課程的情況
?什么叫做同時(shí)存在‘01‘和’02‘課程
?這里是指cid=’01‘ and cid ='02'?
理清思路:同一個(gè)學(xué)生既選了01課程,又選了02課程
1.2 查詢存在" 01 "課程但可能不存在" 02 "課程的情況(不存在時(shí)顯示為 null )
?如何讓不存在某課程時(shí)顯示為null
利用左關(guān)聯(lián)(left join)
?case when--no
1.3 查詢不存在" 01 "課程但存在" 02 "課程的情況
思路:找到不存在01課程的記錄后,
然后再進(jìn)行關(guān)聯(lián)(Inner join)找存在02的課程
或者
2.查詢平均成績(jī)大于等于 60 分的同學(xué)的學(xué)生編號(hào)和學(xué)生姓名和平均成績(jī)
思路:
成績(jī)?cè)趕c表,學(xué)生姓名在student表,二者可以通過學(xué)生編號(hào)sid進(jìn)行關(guān)聯(lián)。
首先,從sc表中查詢平均成績(jī)大于60的學(xué)生的信息
ERROR 1111 (HY000): Invalid use of group function
出現(xiàn)這個(gè)錯(cuò)就要往group by這里考慮,要記得:group by +having+聚合函數(shù)。
一些錯(cuò)誤嘗試:
成功查詢:
接著:通過學(xué)生編號(hào)sid與student表進(jìn)行關(guān)聯(lián)
發(fā)現(xiàn)結(jié)果明顯不對(duì),
繼續(xù)修改:
注意:多個(gè)表進(jìn)行關(guān)聯(lián)時(shí)要明確字段的歸屬表;查詢聚合函數(shù)的結(jié)果時(shí),比如avg(score),最好進(jìn)行重命名。
存在疑問:
上面兩種寫法的差別就在于 子查詢的avg(score)是否重命名,但是二者的結(jié)果明顯有差異,想請(qǐng)問是為什么?是不是哪里沒注意到?
解答:
mysql對(duì)于group by的特殊規(guī)定:
如果用了group by,select語(yǔ)句里除了group by后面跟著的列名以外,只能有聚合函數(shù)。
如果除了group by后面跟著的列名和聚合函數(shù)還有其他列名,sql就會(huì)只輸出第一行,而且如果是'*',也會(huì)只輸出第一行記錄。
舉例說明:
總結(jié):
如果用了group by +聚合函數(shù),那么在查詢的時(shí)候最好是只查詢聚合函數(shù)(+group by 后的列名)避免在查詢其余字段時(shí)只顯示一條記錄的情況。
注意:聚合函數(shù)是一定要查詢的。
3.查詢?cè)?SC 表存在成績(jī)的學(xué)生信息
思路:
(1)首先確定表:sc表和student表
發(fā)現(xiàn)名字有重復(fù),
(2)利用group by sid去除重復(fù)的學(xué)生信息查詢,具體如下:
注意:更嚴(yán)謹(jǐn)?shù)膶懛ǎ?/p>
(1)先寫查詢分組字段的子查詢
(2)將(1)中的字段進(jìn)行嵌套查詢
注意:group by是分開寫的
4.查詢所有同學(xué)的學(xué)生編號(hào)、學(xué)生姓名、選課總數(shù)、所有課程的總成績(jī)(沒成績(jī)的顯示為 null
(1)確定涉及的表的范圍:
student,sc
(2)
思路:
修改:
(2)
(3)
也可以考慮先連接在查詢,但還是建議上述這種方式。
4.1 查有成績(jī)的學(xué)生信息
(1)首先確定使用的表范圍
sc和student
(2)首先獲得成績(jī)表上的學(xué)生id
(3)根據(jù)id去查學(xué)生信息
?這個(gè)和第三題是完全一樣的嗎
回答:思路基本一致。
參考答案:
思路是:看學(xué)生表上的id是否在sc表的id中(即,判斷存在)in/exists
5.查詢「李」姓老師的數(shù)量
6.查詢學(xué)過「張三」老師授課的同學(xué)的信息
(1)四張表都要用到
(2)四個(gè)嵌套
有什么簡(jiǎn)便方法嗎?
回答:參考答案也是逐步嵌套查詢實(shí)現(xiàn)的。
7.查詢沒有學(xué)全所有課程的同學(xué)的信息
(1)關(guān)鍵詞:‘所有課程’在course表,‘同學(xué)信息’在student表,但是二者需要sid進(jìn)行關(guān)聯(lián),所以還需要用到sc表
(2)如何篩選'所有課程’??
利用課程數(shù)目來(lái)進(jìn)行限定。
a.course表獲取總課程數(shù)
b.按照sid分組,對(duì)sc表中的課程數(shù)進(jìn)行計(jì)數(shù)
c.接著從sc中篩選出課程數(shù)=3的學(xué)生sid
d.查詢(3)中對(duì)應(yīng)學(xué)生sid的學(xué)生信息
8.查詢至少有一門課與學(xué)號(hào)為" 01 "的同學(xué)所學(xué)相同的同學(xué)的信息
(1)關(guān)鍵詞:
‘至少有一門課’--課程in學(xué)號(hào)01同學(xué)的課程,‘學(xué)號(hào)01同學(xué)的課程’--course表,‘同學(xué)信息’--student表
(2)思路:
a. 01同學(xué)學(xué)習(xí)了什么課程
發(fā)現(xiàn)01同學(xué)三門課程都學(xué)了,所以其余學(xué)生只要學(xué)習(xí)的課程數(shù)大于0即可。
b. 學(xué)號(hào)01之外的學(xué)生id有哪些
c. 如何查詢其余學(xué)生的課程信息,比如cid?
利用其余學(xué)生的id進(jìn)行分組再計(jì)數(shù),篩選
出次數(shù)大于0的學(xué)生id,再根據(jù)該id進(jìn)行學(xué)生信息的查詢。
9.查詢和" 01 "號(hào)的同學(xué)學(xué)習(xí)的課程 完全相同的其他同學(xué)的信息
(1)確定相關(guān)表:
’01號(hào)同學(xué)學(xué)習(xí)的課程‘-sc表;
’其他同學(xué)的信息‘-student表;
(2)思路:
a. 01號(hào)同學(xué)學(xué)習(xí)了哪些課程
發(fā)現(xiàn)01同學(xué)學(xué)了三門課,
b.再查詢總共有幾門課?
所以,總共有3門課,01同學(xué)全部學(xué)習(xí)了,
c. 查詢其余學(xué)生中學(xué)習(xí)課程數(shù)目為3的學(xué)生id
d. 再跟進(jìn)相應(yīng)id在student表中查詢學(xué)生信息
10.查詢沒學(xué)過"張三"老師講授的任一門課程的學(xué)生姓名
(1)確定相關(guān)表:
‘張三老師tid’--teacher;
‘張三老師授課cid’--course;
‘被授課的學(xué)生sid’--sc;
‘學(xué)生姓名sname’--student;
先找出學(xué)習(xí)過張三老師課程的學(xué)習(xí),再not in即可。
(2)思路:
a.從teacher表中查詢張三老師的tid
b.從course表中查詢張三老師的授課cid
c. 從sc中查詢學(xué)習(xí)cid=02的學(xué)生sid
d.利用not in 查詢沒學(xué)過張三老師課程的學(xué)生信息
11.查詢兩門及其以上不及格課程的同學(xué)的學(xué)號(hào),姓名及其平均成績(jī)
(1)根據(jù)關(guān)鍵字確定相關(guān)表:
‘不及格課程數(shù)2’ score60--sc表,且count(1)3
'姓名'--student 表
(2)思路:
a. 從sc表查詢score小于60的sid,并根據(jù)sid分組計(jì)數(shù)
b.內(nèi)連接得到不及格課程數(shù)目大于等于2的sid,sname以及avg_score
12.檢索" 01 "課程分?jǐn)?shù)小于 60,按分?jǐn)?shù)降序排列的學(xué)生信息
(1)根據(jù)關(guān)鍵詞確定相關(guān)表:
‘01課程分?jǐn)?shù)小于60’ --sc表
‘學(xué)生信息’--student
(2)思路及實(shí)現(xiàn):
a.先從sc表查詢01課程分?jǐn)?shù)小于60并按分?jǐn)?shù)降序排列的學(xué)生信息
b.根據(jù)(1)中的sid從student中查詢學(xué)生信息
13.按平均成績(jī)從高到低顯示所有學(xué)生的所有課程的成績(jī)以及平均成績(jī)
(1)根據(jù)關(guān)鍵詞確定相關(guān)表
‘平均成績(jī)’--sc表
(2)思路及實(shí)現(xiàn)過程:
a. 先按照平均成績(jī)從高到低顯示學(xué)生sc
還要顯示每個(gè)學(xué)生的每一科目的成績(jī)嗎?
回答:是的,給sc表增加一列avg_score。
14.查詢各科成績(jī)最高分、最低分和平均分: 以如下形式顯示:課程 ID,課程 name,最高分,最低分,平均分,及格率,中等率,優(yōu)良率,優(yōu)秀率 及格為=60,中等為:70-80,優(yōu)良為:80-90,優(yōu)秀為:=90 要求輸出課程號(hào)和選修人數(shù),查詢結(jié)果按人數(shù)降序排列,若人數(shù)相同,按課程號(hào)升序排列
(1)根據(jù)關(guān)鍵詞確定相關(guān)表:
‘成績(jī)’ --sc;
‘課程name’--course;
(2)思路及實(shí)現(xiàn):
a. 按照cid對(duì)sc表進(jìn)行分組,并進(jìn)行初步聚合函數(shù)的查詢
b.繼續(xù)完善
?如何計(jì)算各種率
回答:考察條件計(jì)數(shù)的技巧 case when
修改成題目要求格式:
15.按各科成績(jī)進(jìn)行排序,并顯示排名, Score 重復(fù)時(shí)保留名次空缺
(1)根據(jù)關(guān)鍵詞確定相關(guān)表:
sc表
(2)思路:
借助賦值變量@i實(shí)現(xiàn)
a.原始數(shù)據(jù)增加一列@rank
b.
沒有指定關(guān)聯(lián)條件的inner join (笛卡爾積),每一行都會(huì)與之進(jìn)行關(guān)聯(lián)
注意:
前言
案例取自極客時(shí)間《mysql45講》
案例
模擬執(zhí)行器分析查詢語(yǔ)句
場(chǎng)景復(fù)現(xiàn)
奇了怪了,此時(shí)沒用索引,進(jìn)行了全表掃描
雖然使用了索引,但是還是掃描了37116行,不妨結(jié)合之前的知識(shí)分析一下:
1.另一個(gè)事務(wù)未提交,需要保存之前的數(shù)據(jù)的數(shù)據(jù)版本,因此delete10萬(wàn)行數(shù)據(jù)實(shí)際是標(biāo)記數(shù)據(jù),這樣每一行數(shù)據(jù)就有兩個(gè)數(shù)據(jù)版本,舊的是delete之前的,新的是標(biāo)記為delete的,索引a上的數(shù)據(jù)有兩份
2.那還多出來(lái)的1萬(wàn)7呢,之前介紹過索引樹的葉子節(jié)點(diǎn)存的是主鍵,select * 還要進(jìn)行回表查詢,這里將回表的掃描行數(shù)一并算上
為什么會(huì)選錯(cuò)索引
選擇索引是優(yōu)化器的工作,優(yōu)化器要找到最優(yōu)的執(zhí)行方案并選擇最小的代價(jià)去執(zhí)行,掃描行數(shù)是影響執(zhí)行代價(jià)之一(掃描越小,訪問磁盤次數(shù)越少,消耗CPU資源越少)
mysql執(zhí)行語(yǔ)句之前需要通過根據(jù)信息來(lái)統(tǒng)計(jì)記錄數(shù)
這個(gè)統(tǒng)計(jì)信息就是索引的區(qū)分度,即索引上不同的值越多,區(qū)分度越高越好(show index t 的 cardinality字段查看),索引的區(qū)分度是利用采樣統(tǒng)計(jì)得到的即取小部分統(tǒng)計(jì)信息再乘以整體。
除了使用統(tǒng)計(jì)信息,還會(huì)計(jì)算回表代價(jià)(主鍵不需要回表)
如果是統(tǒng)計(jì)信息不對(duì)那就修正
另一種場(chǎng)景復(fù)現(xiàn)
按理說這是個(gè)空集,利用索引a只掃描1000行,利用索引b要掃描50000行,這里優(yōu)化器竟然選擇了索引b??!
mysql又選錯(cuò)了索引
解決辦法
2.引導(dǎo)使用a索引
我們知道索引樹上的數(shù)據(jù)是有序的,優(yōu)化器使用b索引,一方面是認(rèn)為索引b可以避免排序 ,order by a,b強(qiáng)制按照a,b排序意味著兩個(gè)都需要排序,因此掃描行數(shù)成了影響決策的主要條件
3.刪掉索引b
解決mysql選錯(cuò)索引主要有兩大方向
1.強(qiáng)制指定索引
2.干涉優(yōu)化器選擇(比如增大limit數(shù)量,增加order by ,寫成子查詢)
MySQL選錯(cuò)索引導(dǎo)致的線上慢查詢事故
mysql中走與不走索引的情況匯集(待全量實(shí)驗(yàn))
眾所周知, MySQL的驅(qū)動(dòng)表與被驅(qū)動(dòng)表是優(yōu)化器自動(dòng)優(yōu)化選擇的結(jié)果 (與表連接的前后順序等無(wú)關(guān)),我們可以用explain執(zhí)行計(jì)劃來(lái)知曉:
如上所示,前面一行t1是驅(qū)動(dòng)表,后面一行t2是被驅(qū)動(dòng)表。那么驅(qū)動(dòng)表與被驅(qū)動(dòng)表的選擇是否有規(guī)律可循呢?下面是百度搜索兩個(gè)主流的博文對(duì)驅(qū)動(dòng)表與被驅(qū)動(dòng)表的闡釋:
1. MySQL連接查詢驅(qū)動(dòng)表被驅(qū)動(dòng)表以及性能優(yōu)化 - 阿偉~ - 博客園 博文A 主要結(jié)論:
2. mysql驅(qū)動(dòng)表與被驅(qū)動(dòng)表及join優(yōu)化_java小小小黑的博客-CSDN博客_mysql驅(qū)動(dòng)表和被驅(qū)動(dòng)表 博文B 其主要結(jié)論:
兩個(gè)帖子的結(jié)論是都差不多,而且還給出了例子來(lái)佐證。那么網(wǎng)上的結(jié)論是否權(quán)威?是否有普遍性?是否存在缺陷?
讓我們來(lái)一起打破砂鍋問到底。下面有兩張表結(jié)構(gòu)一模一樣的表t1,t2:其中t1 100條數(shù)據(jù),t2 1000條數(shù)據(jù);t1(t2)結(jié)構(gòu)如下:
按照上面博文的結(jié)論,left join左邊是t2表,應(yīng)該是驅(qū)動(dòng)表。我們查看下結(jié)果:
與 博文B 中觀點(diǎn)1相違背(同理觀點(diǎn)2也違背),與實(shí)際不符,但究竟這是為什么呢?
下面發(fā)一張MySQL的執(zhí)行過程(來(lái)源于《MySQL實(shí)戰(zhàn)45講》中01講【一條SQL查詢語(yǔ)句是如何執(zhí)行的】)
so die si ne,原來(lái)sql執(zhí)行的過程是這樣呀。等等,不對(duì),這跟剛才SQL又有什么關(guān)系,上面left join中t2表還是左邊的呀。
我們知道MySQL高版本的性能越來(lái)越好,它是不斷進(jìn)行優(yōu)化迭代的。遠(yuǎn)古的mysql版本可能還需要人工把小表放在前面,大表放在后面等這些需要人工調(diào)優(yōu)的經(jīng)驗(yàn)早就已經(jīng)被解決了。也就是說我們寫的語(yǔ)句,MySQL為了追求更好的效率,它在執(zhí)行器執(zhí)行前已經(jīng)幫我們優(yōu)化了。那么實(shí)際優(yōu)化后的sql如何查看呢?用show warning命令:
其中Message就是優(yōu)化后實(shí)際執(zhí)行的sql語(yǔ)句,格式化后如下:
優(yōu)化后left join左連接變成了內(nèi)連接(inner) join。所以用優(yōu)化后的sql看,表t1是小表所以作為驅(qū)動(dòng)表,與實(shí)際結(jié)果相符。
left join 竟然優(yōu)化成了join,太神奇了,但這是為什么呢?原因在于mysql中null與任何值做等值或者不等值比較的時(shí)候都是null,即使是select null=null 也是null。這樣where 條件t1.a=t2.a查詢條件不會(huì)包含t2.a為NULL的行,實(shí)際效果其實(shí)跟join一樣,被優(yōu)化器智能的優(yōu)化了。
我們直接看執(zhí)行計(jì)劃看實(shí)際結(jié)果吧:
結(jié)果顯示t2是驅(qū)動(dòng)表,t1是被驅(qū)動(dòng)表。t2是1000條數(shù)據(jù)按理說是大表應(yīng)該是被驅(qū)動(dòng)表,與 博文A , 博文B 的結(jié)論又不一致了。
《MySQL實(shí)戰(zhàn)45講》中34講【到底可不可以使用join】已經(jīng)講的很透徹了,很深入了,我就不在這里獻(xiàn)丑了。啰嗦幾句大概就是驅(qū)動(dòng)表是全表掃描不走索引,所以選被驅(qū)動(dòng)表t1可以走索引,不會(huì)全表掃描,減少IO次數(shù),性能高。里面對(duì)大表小表的總結(jié),簡(jiǎn)直是精髓,特意在此再次著重強(qiáng)調(diào):
在決定哪個(gè)表做驅(qū)動(dòng)表的時(shí)候,應(yīng)該是兩個(gè)表按照各自的條件過濾,過濾完成之后,計(jì)算參與join的各個(gè)字段的總數(shù)據(jù)量,數(shù)據(jù)量小的那個(gè)表,就是“小表”,應(yīng)該作為驅(qū)動(dòng)表。
按照上面分析,我們先獨(dú)立思考下MySQL會(huì)選擇哪張表作為驅(qū)動(dòng)表呢?
表t1,t2在字段a上都有索引不會(huì)全表掃描,其中t1.a=5條件過濾后只有一條,很顯然嘛,t1數(shù)據(jù)量少是小表,肯定是驅(qū)動(dòng)表,錯(cuò)不了,再說了前面的紅色粗體已經(jīng)強(qiáng)調(diào)了,不會(huì)有錯(cuò)的。
有冇搞錯(cuò)?事實(shí)又被打臉了。還記得在開篇我們說過的mysql優(yōu)化器會(huì)對(duì)sql語(yǔ)句進(jìn)行優(yōu)化的嗎?下面我們看下執(zhí)行計(jì)劃與優(yōu)化的sql語(yǔ)句:
格式化后的優(yōu)化SQL如下:
優(yōu)化后兩表t1,t2都走索引,并且都只有一條結(jié)果返回,因此都只會(huì)掃描一行,數(shù)據(jù)量一樣,所以誰(shuí)在前面誰(shuí)就是驅(qū)動(dòng)表,也就是上面sql中表t2。一切都釋然,豁然開通!
回頭再仔細(xì)想想,高,實(shí)在是高!仔細(xì)深思之后MySQL優(yōu)化后的句子真讓人猛拍大腿。高明之處在于:
1. 本來(lái)join連接是個(gè)M*N的嵌套循環(huán),優(yōu)化后變成了M+N的判斷,兩表不再嵌套判斷了。
2. 優(yōu)化后,兩表沒有多大必然聯(lián)系,只需把兩表的結(jié)果集拼接即可,互不干擾。如果mysql未來(lái)可以多線程查詢,豈不十分快哉!
小伙伴們還記得我們?cè)谏弦徽? MySQL索引初探 中編碼類型不一致發(fā)生隱式轉(zhuǎn)換時(shí)有時(shí)候走索引,有時(shí)候索引又失效的問題嗎?下面我們選取有代表性的一條記錄來(lái)分析:
其中表demo_test總共有640條數(shù)據(jù),demo_test_ass有3條數(shù)據(jù)。顯然經(jīng)過過濾條件t.rid1完成后demo_test_ass數(shù)據(jù)量小,應(yīng)該作為驅(qū)動(dòng)表。雖然test.c_utf8mb4 = t.c2兩字段連接中發(fā)生了t.c2字段發(fā)生隱式轉(zhuǎn)換,但是實(shí)際上并不影響被驅(qū)動(dòng)表test上的c_utf8mb4索引。
好了,本章到此結(jié)束,讓我們一起 總結(jié)一下MySQL驅(qū)動(dòng)表與被驅(qū)動(dòng)表的選取原則 :
?? ? 同等條件,優(yōu)先選取有索引的表作為被驅(qū)動(dòng)表。 在此介紹一下什么叫同等條件,比如上面的②中的語(yǔ)句。 兩表沒有其他額外的過濾條件,因此選關(guān)聯(lián)字段有索引的t1作為被驅(qū)動(dòng)表。但是如果加了條件(and t1.id=3),此時(shí)t1數(shù)據(jù)量少,就選取了t2作為被驅(qū)動(dòng)表。
??? MySQL選擇驅(qū)動(dòng)表與被驅(qū)動(dòng)表是基于優(yōu)化器優(yōu)化后的,小表是驅(qū)動(dòng)表,大表是被驅(qū)動(dòng)表。 基于優(yōu)化器優(yōu)化后開篇的 博文A與B 結(jié)論成立。
當(dāng)然這都是我一家之言,并不是官方結(jié)論,目前暫未找到官方確切對(duì)于驅(qū)動(dòng)表與被驅(qū)動(dòng)表的解釋,請(qǐng)大家踴躍拍磚!
我學(xué)習(xí)Java 已經(jīng)快四年了,在 Java 學(xué)習(xí)這條路上也踩過無(wú)數(shù)次的坑,恰巧有小伙伴問我 Java 學(xué)習(xí)的路線,我想著趁這次機(jī)會(huì)分享自己學(xué) Java 的路線,希望給小伙伴們一點(diǎn)幫助,避開路上的一些坑
小伙伴們有興趣想了解內(nèi)容和更多相關(guān)學(xué)習(xí)資料的請(qǐng)點(diǎn)贊收藏+評(píng)論轉(zhuǎn)發(fā)+關(guān)注我,后面會(huì)有很多干貨。我有一些面試題、架構(gòu)、設(shè)計(jì)類資料可以說是程序員面試必備!
所有資料都整理到網(wǎng)盤了,需要的話歡迎下載!私信我回復(fù)【111】即可免費(fèi)獲取
首先,我先分享下自己對(duì)不同學(xué)習(xí)方式的理解,小伙伴們可以根據(jù)自己情況選擇。
看視頻系統(tǒng)學(xué)習(xí),比如培訓(xùn)機(jī)構(gòu)的課程、MOOC的課程等??匆曨l的好處就是有老師帶著,易于理解和掌握,非常適合初學(xué)者。
看書學(xué)習(xí),如《Redis設(shè)計(jì)與實(shí)現(xiàn)》、《 Java 并發(fā)編程的藝術(shù)》,便于了解技術(shù)脈絡(luò)和深入學(xué)習(xí)知識(shí)點(diǎn)。
看博客和源碼精進(jìn)學(xué)習(xí)。博客的好處是有些知識(shí)點(diǎn)會(huì)以很通俗的方式講解出來(lái),我們很好理解。
第一階段: Java 基礎(chǔ)
最開始要學(xué)習(xí)的是 Java 基礎(chǔ),學(xué)習(xí)了這部分,就會(huì)對(duì) Java 語(yǔ)言有一個(gè)初步的了解。其實(shí)大部分語(yǔ)言的基礎(chǔ)知識(shí)都是大同小異,如果之前已經(jīng)學(xué)習(xí)過其他語(yǔ)言如C、C++,那學(xué)習(xí)這部分會(huì)更快。
這部分主要學(xué)習(xí)的內(nèi)容有:基本程序結(jié)構(gòu),類與對(duì)象,接口,泛型,反射,集合,異常與調(diào)試, Java 網(wǎng)絡(luò)編程, Java I/O和多線程。
學(xué) Java 基礎(chǔ),推薦大家看尚硅谷宋紅康老師的 Java 教程,宋老師的課程更適合零基礎(chǔ)學(xué)員,從 Java 語(yǔ)言起源開始,循序漸進(jìn),知識(shí)點(diǎn)剖析細(xì)致。
除此之外,還可以閱讀《 Java 核心技術(shù) 卷I》,這本書偏向?qū)嵱?,廣度和深度都恰到好處。其中,第7-9章講述了 Java 的GUI編程, Java 的GUI開發(fā)使用并不多,這部分可以先跳過。
網(wǎng)上也有一些不錯(cuò)的文檔教程網(wǎng)站,可以輔助學(xué)習(xí):
菜鳥教程 Java :Java 教程 | 菜鳥教程
當(dāng)學(xué)完了這部分,就可以做個(gè)圖書管理系統(tǒng)、學(xué)生管理系統(tǒng)這樣的小項(xiàng)目了。還記得庫(kù)森在大二學(xué)完這部分,就跟著教程學(xué)做了個(gè)貪吃蛇游戲,還是蠻有成就感的。
當(dāng)然,時(shí)間有限的小伙伴,可以不用做這塊的項(xiàng)目,直接做 Java Web 項(xiàng)目就好了。
第二階段:數(shù)據(jù)庫(kù)
MySQL 和 Oracle 都是廣受企業(yè)歡迎的數(shù)據(jù)庫(kù),其中 MySQL 是目前應(yīng)用最廣泛的開源關(guān)系數(shù)據(jù)庫(kù),對(duì)于新手或者校招的小伙伴,我們目前只學(xué)習(xí) MySQL 就可以了。
這部分主要學(xué)習(xí)的內(nèi)容有:數(shù)據(jù)庫(kù)的CRUD操作、JDBC API、數(shù)據(jù)庫(kù)特性和數(shù)據(jù)庫(kù)連接池。
其中,數(shù)據(jù)庫(kù)連接池是為了避免頻繁地創(chuàng)建和銷毀 JDBC 連接,常見連接池包括 C3P0,Druid 和 HikariCP,目前使用最廣泛的是HikariCP。
書籍方面,推薦入門的小伙伴看《MySQL必知必會(huì)》,是一本小冊(cè)子,這本書實(shí)踐性很強(qiáng),基本沒有什么理論的堆砌,非常適合入門。
如果想要深入學(xué)習(xí),可以看《高性能 MySQL》,這本書是MySQL領(lǐng)域的經(jīng)典之作,不過就是太厚了,面試重點(diǎn)看索引部分就可以了。
除此之外,如果要深入學(xué)習(xí)MySQL的使用和原理,可以看極客時(shí)間的專欄《MySQL實(shí)戰(zhàn)45講》,阿里資深技術(shù)專家講解的課程,有很多生產(chǎn)經(jīng)常遇到的問題,非常有深度。
第三階段: Java Web
學(xué)習(xí) Java Web,我們不僅需要掌握后端 Java 技術(shù),還需要學(xué)習(xí)些前端知識(shí)。
前端有三大基礎(chǔ)技術(shù) Html、CSS和 Java Script,初學(xué)的話,學(xué)習(xí)這些就可以了。如果想做出更好的交互式效果,可以再學(xué)習(xí)Vue和React等前端技術(shù)。
后端 Java 技術(shù)包括 Servlet、Filter、Listener、Session、Cookie、JSP、EL 表達(dá)式和 JSTL 等。
其中,像 JSP 這樣比較老的技術(shù),目前在各大互聯(lián)網(wǎng)公司基本不再使用,已經(jīng)被 Freemark、Thymeleaf 這樣的模板引擎所替代,我們只需要了解基本使用即可。
入門 Java Web,推薦尚硅谷的 Java Web 教程,教程不僅包括前端三大技術(shù),還有后端 Java 技術(shù),最后還會(huì)帶大家做一個(gè)書城項(xiàng)目。
第四階段:主流框架
這部分我們要學(xué)習(xí)的主流框架主要有 Spring、Spring MVC 和 MyBatis,俗稱 SSM 框架。
曾經(jīng)的 SSH 框架,即 Struts2、Spring、Hibernate 框架,已經(jīng)逐漸被 SSM 替代,現(xiàn)在可以不用再學(xué) Struts2 和 Hibernate 框架了。
文章標(biāo)題:mysql45講怎么樣,mysql45講pdf
URL鏈接:http://aaarwkj.com/article42/dssgchc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、外貿(mào)建站、網(wǎng)站維護(hù)、網(wǎng)站內(nèi)鏈、全網(wǎng)營(yíng)銷推廣、營(yíng)銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)