学习笔记之-MySql高级之sql优化
一 Mysql簡介
概述
MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫管理系統(tǒng),由瑞典MySQL AB公司開發(fā),目前屬于Oracle公司。
M/SQL是一種關(guān)聯(lián)數(shù)據(jù)庫管理系統(tǒng),將數(shù)據(jù)保存在不同的表中,而不是將所有數(shù)據(jù)放在一個(gè)大倉庫內(nèi),這樣就增加了速度并提高了靈活性。
Mysql是開源的,所以你不需要支付額外的費(fèi)用。
Mysql支持大型的數(shù)據(jù)庫。可以處理擁有上千萬條記錄的大型數(shù)據(jù)庫。MySQL使用標(biāo)準(zhǔn)的SQL數(shù)據(jù)語言形式。
Mysql可以允許于多個(gè)系統(tǒng)上,并且支持多種語言。這些編程語詈包括C、C++、Python、Java、Perl、PHP、Eifel、Ruby和Tcl等。Mysq|對PHP有很好的支持,PHP是目前最流行的Web開發(fā)語言。
MySQL支持大型數(shù)據(jù)庫,支持5000萬條記錄的數(shù)據(jù)倉庫,32位系統(tǒng)表文件最大可支持4GB,64位系統(tǒng)支持最大的表文件為8TB。Mysql是可以定制的,采用了GPL協(xié)議,你可以修改源碼來開發(fā)自己的Mysql系統(tǒng)。
高級MySQL
mysql內(nèi)核
sql優(yōu)化攻城獅
mysql服務(wù)器的優(yōu)化
各種參教常量設(shè)定
查詢語句優(yōu)化
主從復(fù)制
軟硬件升級
容災(zāi)備份
sql編程
完整的mysql優(yōu)化需要很深的功底,大公司甚至有專門的DBA寫上述
MySql存儲引擎
如何用命令查看
#看你的mysql現(xiàn)在已提供什么存儲引擎:
mysql> show engines;
#看你的mysql當(dāng)前默認(rèn)的存儲引擎:
mysql> show variables like ‘%storage_engine%’;
MyISAM和InnoDB區(qū)別
阿里巴巴、淘寶用哪個(gè)
Percona為MySQL數(shù)據(jù)庫服務(wù)器進(jìn)行了改進(jìn),在功能和性能上較MySQL有著很顯著的提升。該版本提升了在高負(fù)載情況下的InnoDB的性能、為DBA提供一些非常有用的性能診斷工具;另外有更多的參數(shù)和命令來控制服務(wù)器行為。
該公司新建了一款存儲引擎叫xtradb完全可以替代innodb,并且在性能和并發(fā)上做得更好,
阿里巴巴大部分mysql數(shù)據(jù)庫其實(shí)使用的percona的原型加以修改。
AliSql+AliRedis
二 索引優(yōu)化分析
性能下降SQL慢,執(zhí)行時(shí)間長,等待時(shí)間長 的原因
1 查詢語句寫的爛
2 索引失效
單值
idx_user_name 就是索引名稱 給字段name創(chuàng)建索引
復(fù)合
idx_user_nameEmail 就是索引名稱 給name和email創(chuàng)建復(fù)合索引
3 關(guān)聯(lián)查詢太多join(設(shè)計(jì)缺陷或不得已的需求)
太多多表關(guān)聯(lián)查詢也會導(dǎo)致查詢慢
4 服務(wù)器調(diào)優(yōu)及各個(gè)參數(shù)設(shè)置(緩沖、線程數(shù)等)
常見通用的Join查詢
SQL執(zhí)行順序
手寫
機(jī)讀
總結(jié)
Join圖 7種JOIN
7種
索引簡介
索引是什么
MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。可以得到索引的本質(zhì):索引是數(shù)據(jù)結(jié)構(gòu)。
索引的目的在于提高查詢效率,可以類比字典,
如果要查“mysql”這個(gè)單詞,我們肯定需要定位到m字母,然后從下往下找到y(tǒng)字母,再找到剩下的sql。
如果沒有索引,那么你可能需要a—Z,如果我想找到Java開頭的單詞呢﹖或者Oracle開頭的單詞呢?
是不是覺得如果沒有索引,這個(gè)事情根本無法完成?
你可以簡單理解為"排好序的快速查找數(shù)據(jù)結(jié)構(gòu)”。
詳解(重要)
在數(shù)據(jù)之外,數(shù)據(jù)庫系統(tǒng)還維護(hù)著滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)上實(shí)現(xiàn)高級查找算法。這種數(shù)據(jù)結(jié)構(gòu),就是索引。
下圖就是一種可能的索引方式示例:
左邊是數(shù)據(jù)表,一共有兩列七條記錄,最左邊的是數(shù)據(jù)記錄的物理地址
為了加快Col2的查找,可以維護(hù)一個(gè)右邊所示的二叉查找樹,每個(gè)節(jié)點(diǎn)分別包含索引鍵值和一個(gè)指向?qū)?yīng)數(shù)據(jù)記錄物理地址的指針,這樣就可以運(yùn)用二叉查找在一定的復(fù)雜度內(nèi)獲取到相應(yīng)數(shù)據(jù),從而快速的檢索出符合條件的記錄。
結(jié)論
數(shù)據(jù)本身之外,數(shù)據(jù)庫還維護(hù)著一個(gè)滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)以某種方式指向數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)上實(shí)現(xiàn)高級查找算法,這種數(shù)據(jù)結(jié)構(gòu)就是索引。
般來說索引本身也很大,不可能全部存儲在內(nèi)存中,因此索引往往以索引文件的形式存儲的磁盤上
我們平常所說的索引,如果沒有特別指明,都是指B樹(多路搜索樹,并不一定是二叉的)結(jié)構(gòu)組織的索引。其中聚集索引,次要索引,覆蓋索引,復(fù)合索引,前綴索引,唯一索引默認(rèn)都是使用B+樹索引,統(tǒng)稱索引。當(dāng)然,除了B+樹這種類型的索引之外,還有哈稀索引(hashindex)等。
索引優(yōu)勢
類似大學(xué)圖書館建書目索引,提高數(shù)據(jù)檢索的效率,降低數(shù)據(jù)庫的IO成本
通過索引列對數(shù)據(jù)進(jìn)行排序,降低數(shù)據(jù)排序的成本,降低了CPU的消耗
索引劣勢
實(shí)際上索引也是一張表,該表保存了主鍵與索引字段,并指向?qū)嶓w表的記錄,所以索引列也是要占用空間的
雖然索引大大提高了查詢速度,同時(shí)卻會降低更新表的速度,如對表進(jìn)行INSERT、UPDATE和DELETE。因?yàn)楦卤頃r(shí),MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件每次更新添加了索引列的字段,都會調(diào)整因?yàn)楦滤鶐淼逆I值變化后的索引信息
索引只是提高效率的一個(gè)因素,如果你的MySQL有大數(shù)據(jù)量的表,就需要花時(shí)間研究建立最優(yōu)秀的索引.
mysql索引分類
單值索引
即一個(gè)索引只包含單個(gè)列,一個(gè)表可以有多個(gè)單列索引
唯一索引
索引列的值必須唯一,但允許有空值
復(fù)合索引
即一個(gè)索引包含多個(gè)列
基本語法
ALTER命令的使用
mysql索引結(jié)構(gòu)
BTree索引(針對java開發(fā)需要重點(diǎn)了解)
BTree索引的檢索原理
【初始化介紹】
一顆b+樹,淺藍(lán)色的塊我們稱之為一個(gè)磁盤塊,可以看到每個(gè)磁盤塊包含幾個(gè)數(shù)據(jù)項(xiàng)(深藍(lán)色所示)和指針(黃色所示),如磁盤塊1包含數(shù)據(jù)項(xiàng)17和35,包含指針P1、P2、P3,
P1表示小于17的磁盤塊,P2表示在17和35之間的磁盤塊,P3表示大于35的磁盤塊。
真實(shí)的數(shù)據(jù)存在于葉子節(jié)點(diǎn) 即 3、5、9、10、13、15、28、29、36、60、75、79、90、99。
非葉子節(jié)點(diǎn)只不存儲真實(shí)的數(shù)據(jù),只存儲指引搜索方向的數(shù)據(jù)項(xiàng),如17、35并不真實(shí)存在于數(shù)據(jù)表中。
【查找過程】
如果要查找數(shù)據(jù)項(xiàng)29,那么首先會把磁盤塊1由磁盤加載到內(nèi)存,此時(shí)發(fā)生一次IO,在內(nèi)存中用二分查找確定29在17和35之間,鎖定磁盤塊1的P2指針,內(nèi)存時(shí)間因?yàn)榉浅6?#xff08;相比磁盤的I0)可以忽略不計(jì)扌通過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內(nèi)存,發(fā)生第二次I0,29在26和30之間,鎖定磁盤塊3的P2指針,通過指針加載磁盤塊8到內(nèi)存,發(fā)生第三次IO,同時(shí)內(nèi)存中做二分查找找到29,結(jié)束查詢,總計(jì)三次lO。
真實(shí)的情況是,3層的b+樹可以表示上百萬的數(shù)據(jù),如果上百萬的數(shù)據(jù)查找只需要三次IO,性能提高將是巨大的,如果沒有索引,每個(gè)數(shù)據(jù)項(xiàng)都要發(fā)生一次IO,那么總共需要百萬次的IO,顯然成本非常非常高。
Hash索引
full-text全文索引
R-Tree索引
哪些情況需要?jiǎng)?chuàng)建索引
1.主鍵自動(dòng)建立唯一索引
2.頻繁作為查詢條件的字段應(yīng)該創(chuàng)建索引
3.查詢中與其它表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引
4.頻繁更新的字段不適合創(chuàng)建索引 – 因?yàn)槊看胃虏粏螁问歉铝擞涗涍€會更新索引表
5.Where條件里用不到的字段不創(chuàng)建索引
6.單鍵/組合索引的選擇問題,who?(在高并發(fā)下傾向創(chuàng)建組合索引)
7.查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
8.查詢中統(tǒng)計(jì)或者分組字段
哪些情況不要?jiǎng)?chuàng)建索引
1.表記錄太少
2.經(jīng)常增刪改的表:
Why:提高了查詢速度,同時(shí)卻會降低更新表的速度,如對表進(jìn)行INSERT、UPDATE和DELETE。因?yàn)楦卤頃r(shí),MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件
3.數(shù)據(jù)重復(fù)且分布平均的表字段,因此應(yīng)該只為最經(jīng)常查詢和最經(jīng)常排序的數(shù)據(jù)列建立索引。
注意,如果某個(gè)數(shù)據(jù)列包含許多重復(fù)的內(nèi)容,為它建立索引就沒有太大的實(shí)際效果。
性能分析
MySql Query Optimizer
1 Mysql中有專門負(fù)責(zé)優(yōu)化SELECT語句的優(yōu)化器模塊,主要功能:通過計(jì)算分析系統(tǒng)中收集到的統(tǒng)計(jì)信息,為客戶端請求的Query提供他認(rèn)為最優(yōu)的執(zhí)行計(jì)劃(他認(rèn)為最優(yōu)的數(shù)據(jù)檢索方式,但不見得是DBA認(rèn)為是最優(yōu)的,這部分最耗費(fèi)時(shí)間)
2 當(dāng)客戶端向MySQL請求一條Query,命令解析器模塊完成請求分類,區(qū)別出是SELECT并轉(zhuǎn)發(fā)給MySQL Query Optimizer時(shí),MySQL Query Optimizer首先會對整條Query進(jìn)行優(yōu)化,處理掉一些常量表達(dá)式的預(yù)算,直接換算成常量值。并對Query中的查詢條件進(jìn)行簡化和轉(zhuǎn)換,如去掉一些無用或顯而易見的條件、結(jié)構(gòu)調(diào)整等。然后分析Query 中的Hint信息(如果有)﹐看顯示Hint信息是否可以完全確定該Query的執(zhí)行計(jì)劃。如果沒有Hint或Hint信息還不足以完全確定執(zhí)行計(jì)劃,則會讀取所涉及對象的統(tǒng)計(jì)信息,根據(jù)Query進(jìn)行寫相應(yīng)的計(jì)算分析,然后再得出最后的執(zhí)行計(jì)劃。
MySQL常見瓶頸
CPU:CPU在飽和的時(shí)候一般發(fā)生在數(shù)據(jù)裝入內(nèi)存或從磁盤上讀取數(shù)據(jù)時(shí)候
IO:磁盤I/o瓶頸發(fā)生在裝入數(shù)據(jù)遠(yuǎn)大于內(nèi)存容量的時(shí)候
服務(wù)器硬件的性能瓶頸: top,free, iostat和vmstat來查看系統(tǒng)的性能狀態(tài)
Explain(重點(diǎn)) 解釋
是什么(查看執(zhí)行計(jì)劃)
使用EXPLAIN關(guān)鍵字可以模擬優(yōu)化器執(zhí)行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結(jié)構(gòu)的性能瓶頸
官網(wǎng)介紹
http://dev.mysql.com/doc/refman/5.5/en/explain-output.html
能干嘛
表的讀取順序
數(shù)據(jù)讀取操作的操作類型
哪些索引可以使用
哪些索引被實(shí)際使用
表之間的引用
每張表有多少行被優(yōu)化器查詢
怎么玩
Explain + SQL語句
執(zhí)行計(jì)劃包含的信息
各字段解釋
id
select查詢的序列號,包含一組數(shù)字,表示查詢中執(zhí)行select子句或操作表的順序
三種情況
一: id相同,執(zhí)行順序由上至下
二: id不同,如果是子查詢 ,id的序號會遞增,id值越大優(yōu)先級越高,越先被執(zhí)行
三: id相同不同,同時(shí)存在
select_type
有哪些
查詢的類型,主要是用于區(qū)別普通查詢、聯(lián)合查詢、子查詢等的復(fù)雜查詢
1.SIMPLE 簡單的select查詢,查詢中不包含子查詢或者UNION
2.PRIMARY 查詢中若包含任何復(fù)雜的子部分,最外層查詢則被標(biāo)記為
3.SUBQUERY 在SELECT或WHERE列表中包含了子查詢
4.DERIVED
在FROM列表中包含的子查詢被標(biāo)記為DERIVED(衍生)
MySQL會遞歸執(zhí)行這些子查詢,把結(jié)果放在臨時(shí)表里。
5.UNION
若第二個(gè)SELECT出現(xiàn)在UNION之后,則被標(biāo)記為UNION;
若UNION包含在FROM子句的子查詢中,外層SELECT將被標(biāo)記為:DERIVED
6.UNION RESULT 從UNION表獲取結(jié)果的SELECT
table
顯示這一行的數(shù)據(jù)是關(guān)于哪張表的
type
訪問類型排列
type顯示的是訪問類型,是較為重要的一個(gè)指標(biāo),結(jié)果值從最好到最壞依次是:
system > const > eq_ref > ref > fultext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >ALL
常見的 從最好到最差依次是: system>const>eq_ref>ref>range>index>ALL
一般來說,得保證查詢至少達(dá)到range級別,最好能達(dá)到ref。
顯示查詢使用了何種類型 從最好到最差依次是:system>const>eq_ref>ref>range>index>ALL
system 表只有一行記錄(等于系統(tǒng)表),這是const類型的特列,平時(shí)不會出現(xiàn),這個(gè)也可以忽略不計(jì)
const 表示通過索引一次就找到了,const用于比較primary key或者unique索引。因?yàn)橹黄ヅ湟恍袛?shù)據(jù),所以很快如將主鍵置于where列表中,MySQL就能將該查詢轉(zhuǎn)換為一個(gè)常量
eq_ref 唯一性索引掃描,對于每個(gè)索引鍵,表中只有一條記錄與之匹配。常見于主鍵或唯一索引掃描
ref 非唯一性索引掃描,返回匹配某個(gè)單獨(dú)值的所有行.本質(zhì)上也是一種索引訪問,它返回所有匹配某個(gè)單獨(dú)值的行,然而,它可能會找到多個(gè)符合條件的行,所以他應(yīng)該屬于查找和掃描的混合體
range 只檢索給定范圍的行,使用一個(gè)索引來選擇行。key列顯示使用了哪個(gè)索引一般就是在你的where語句中出現(xiàn)了between、<、>、in等的查詢 ,這種范圍掃描索引掃描比全表掃描要好,因?yàn)樗恍枰_始于索引的某一點(diǎn),而結(jié)束語另一點(diǎn),不用掃描全部索引。
index Full Index Scan,index與ALL區(qū)別為index類型只遍歷索引樹。這通常比ALL快,因?yàn)樗饕募ǔ1葦?shù)據(jù)文件小。(也就是說雖然all和Index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)
All Full Table Scan,將遍歷全表以找到匹配的行
possible_keys
顯示可能應(yīng)用在這張表中的索引,一個(gè)或多個(gè)。
查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實(shí)際使用
key
實(shí)際使用的索引。如果為NULL,則沒有使用索引
查詢中若使用了覆蓋索引,則該索引僅出現(xiàn)在key列表中
雖然possible_keys 理論上沒有使用索引,但是建立的索引與查詢的字段相符,這樣就使用了索引
key_len
表示索引中使用的字節(jié)數(shù),可通過該列計(jì)算查詢中使用的索引的長度。在不損失精確性的情況下,長度越短越好
key_len顯示的值為索引字段的最大可能長度,并非實(shí)際使用長度,即key_len是根據(jù)表定義計(jì)算而得,不是通過表內(nèi)檢索出的
ref
顯示索引的哪一列被使用了,如果可能的話,是一個(gè)常數(shù)。哪些列或常量被用于查找索引列上的值
由key_len可知t1表的idx_col1_col2被充分使用,col1匹配t2表的col1,col2匹配了一個(gè)常量,即 ‘a(chǎn)c’
查詢中與其它表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引
rows
根據(jù)表統(tǒng)計(jì)信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數(shù)
Extra 包含不適合在其他列中顯示但十分重要的額外信息
1.Using filesort 說明mysql會對數(shù)據(jù)使用一個(gè)外部的索引排序,而不是按照表內(nèi)的索引順序進(jìn)行讀取。
MySOL中無法利用索引完成的排序操作稱為"文件排序”
發(fā)現(xiàn)第一次查詢出現(xiàn)Using filesort,如果能夠優(yōu)化不出現(xiàn),就想第二次執(zhí)行的語句一樣最好,不出現(xiàn)效率更高
2.**Using temporary**使了用臨時(shí)表保存中間結(jié)果,MysQL在對查詢結(jié)果排序時(shí)使用臨時(shí)表。常見于排序order by和分組查詢group by.
group by 若建立了索引,那么就都要在group by后使用這個(gè)索引,或者復(fù)合索引都要用到,才會是sql效率高,不會出現(xiàn)Using filesort和Using temporary
3.USING index 效率不錯(cuò)!
表示相應(yīng)的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的數(shù)據(jù)行
效率不錯(cuò)!
如果同時(shí)出現(xiàn)using where,表明索引被用來執(zhí)行索引鍵值的查找;
如果沒有同時(shí)出現(xiàn)using where,表明索引用來讀取數(shù)據(jù)而非執(zhí)行查找動(dòng)作。
覆蓋索引(Covering Index) : 建立的索引剛好是select 字段 from 中查詢的字段
一搬說為索引覆蓋。
理解方式一:就是select的數(shù)據(jù)列只用從索引中就能夠取得,不必讀取數(shù)據(jù)行,MySQL可以利用索引趙回select列表中的子段,川不必根據(jù)索引再次讀取數(shù)據(jù)文件,換句話說查詢列要被所建的索引覆蓋。
理解方式二:索引是高效找到行的一個(gè)方法,但是一般數(shù)據(jù)庫也能使用索引找到一個(gè)列的數(shù)據(jù),因此它不必讀取整個(gè)行。畢竟索引葉子節(jié)點(diǎn)存儲了它們索引的數(shù)據(jù);當(dāng)能通過讀取索引就可以得到想要的數(shù)據(jù),那就不需要讀取行了。一個(gè)索引包含了(或覆蓋了)滿足查詢結(jié)果的數(shù)據(jù)就叫做覆蓋索引。
注意:
如果要使用覆蓋索引,一定要注意select列表中只取出需要的列,不可select *,因?yàn)槿绻麑⑺凶侄我黄鹱鏊饕龝?dǎo)致索引文件過大,查詢性能下降。
4.Using where 表明使用了where過濾
5.using join buffer 使用了連接緩存:
6.impossible where where子句的值總是false,不能用來獲取任何元組
7.select tables optimized away 在沒有GROUPBY子句的情況下,基于索引優(yōu)化MIN/MAX操作或者
對于MyISAM存儲引擎優(yōu)化COUNT(*)操作,不必等到執(zhí)行階段再進(jìn)行計(jì)算,查詢執(zhí)行計(jì)劃生成的階段即完成優(yōu)化。
8.distinct 優(yōu)化distinct操作,在找到第一匹配的元組后即停止找同樣值的動(dòng)作
索引優(yōu)化
索引分析
單表
建表SQL
CREATE TABLE IF NOT EXISTS `article`( `id`INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, `author_id` INT(10)UNSIGNED NOT NULL, `category_id` INT(10)UNSIGNED NOT NULL, `views`INT(10)UNSIGNED NOT NULL, `comments`INT(10)UNSIGNED NOT NULL, `title`VARBINARY(255) NOT NULL, `content`TEXT NOT NULL );INSERT INTO `article` ( author_id , `category_id` , `views`,`comments`, `title`, `content`) VALUES (1,1,1,1,'1','1'), (2,2,2,2,'2','2'), (1,1,3,3,'3','3');案例
1.查詢category_id為1且comments大于1的情況下,views最多的article_id。
上面的分析sql結(jié)論:很顯然,type是ALL,即最壞的情況。Extra里還出現(xiàn)了Using filesort,也是最壞的情況。優(yōu)化是必須的。
發(fā)現(xiàn)此表根本沒有索引
開始優(yōu)化:
#1.1新建索引+刪除索引
建立索引的兩種sql語句
ALTER TABLE 'article’ADD INDEX idx_article_ccv ( ‘category_id’, 'comments '; ‘views’);create index idx_article_ccv on article(category_id,comments,views);
create index idx _article_ccv on article(category_id,comments,views);
再次查看索引:show index from artic1e;
再次分析sql
雖然使用到了索引,但是還是存在using filesort
結(jié)論:范圍以后索引失效,但是是需求是范圍查詢,所以當(dāng)前建立索引不適合當(dāng)前業(yè)務(wù)需求
刪除索引后再次分析
DROP INDEX idx_article_ccv ON article
刪除后= 與 > 都出現(xiàn)文件排序using filesort
#1.2第2次EXPLAIN
EXPLAIN SELECT id,author_id FROM article"WHEREcategory_id=1 AND comments >10RDERBY views DESC LIMIT1;EXPLAIN SELECT id,author_id FROM article 'WHEREcategory_id=1AND comments =3 ORDER BY views DESCLIMIT1
#結(jié)論:
#type變成了range,這是可以忍受的。但是extra里使用Using filesort仍是無法接受的。
#但是我們已經(jīng)建立了索引,為啥沒用呢?
#這是因?yàn)榘凑誃Tree 索引的工作原理,
#先排序category_id,
#如果遇到相同的category_id則再排序comments,如果遇到相同的comments則再排序views。
#當(dāng)comments字段在聯(lián)合索引里處于中間位置時(shí),
#因comments >1條件是一個(gè)范圍值(所謂range),
#MySQL無法利用索引再對后面的views部分進(jìn)行檢索,即range類型查詢字段后面的索引無效。
#1.3刪除第一次建立的索引
DROP INDEX idx_article_ccv ON article;
#1.4第2次新建索引
#ALTERTABLE 'article’ADD INDEX idx_article_cv ( ‘category_id’ , 'views` ) ;create index idx_article_cv on article(category_id,views:
#結(jié)論:可以看到,type變?yōu)榱藃ef,Extra中的Using filesort也消失了,結(jié)果非常理想。DROP INDEX idx_article_cv ON article;
兩表
建表SQL
CREATE TABLE IF NOT EXISTS `class` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`card` INT(10)UNSIGNED NOT NULL, PRIMARY KEY (id) );CREATE TABLE IF NOT EXISTS `book` ( `bookid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `card`INT(10)UNSIGNED NOT NULL, PRIMARY KEY (`bookid`) );INSERT INTO class(card) VALUES(FLOOR(1+(RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 +(RAND()* 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND()* 20)));關(guān)聯(lián)查詢
案例
下面開始explain分析
EXPLAIN SELECT* FROM class LEFT JOIN book ON class.card = book.card;
#結(jié)論: type有All
我們需要添加索引優(yōu)化,但是不知道加在左表還是右表啊,那么就試一試,看看那個(gè)效率高,在得出正確的添加索引結(jié)論
添加索引優(yōu)化
ALTER TABLE book ADD INDEXY ( card);
左連接將索引加右表分析
刪除剛加的索引
左連接將索引加在左表分析
結(jié)論: 兩表,左右連接索引相反加,sql執(zhí)行效率高
EXPLAIN SELECT*FROM class LEFT JOIN book ON class.card = book.card;
#可以看到第二行的type變?yōu)榱藃ef,rows也變成了優(yōu)化比較明顯。
#這是由左連接特性決定的。LEFTJOIN條件用于確定如何從右表搜索行,左邊一定都有,
#所以右邊是我們的關(guān)鍵點(diǎn),一定需要建立索引。
三表
建表SQL
CREATE TABLE IF NOT EXISTS `class` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`card` INT(10)UNSIGNED NOT NULL, PRIMARY KEY (id) );CREATE TABLE IF NOT EXISTS `book` ( `bookid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `card`INT(10)UNSIGNED NOT NULL, PRIMARY KEY (`bookid`) );INSERT INTO class(card) VALUES(FLOOR(1+(RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 +(RAND()* 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO class(card) VALUES(FLOOR(1 + (RAND()* 20)));CREATE TABLE IF NOT EXISTS`phone`( `phoneid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `card` INT(10) UNSIGNED NOT NULL, PRIMARY KEY (`phoneid`) )ENGINE = INNODB;INSERT INTO phone(card) VALUES(FLOOR(1+(RAND( * 20))); INSERT INTO phone(card) VALUES(FLOOR(1+(RAND() * 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND() * 20); INSERT INTO phone(card) VALUES(FLOOR(1 + (RAND()* 20)); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND()* 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND()* 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND()* 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND()* 20))); INSERT INTO phone(card) VALUES(FLOOR(1+(RAND() * 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND() * 20))); INSERT INTO phone(card) VALUES(FLOOR(1 +(RAND() * 20)));查看
案例
SELECT * FROM class LEFT JOIN book ON class.card=book.card LEFT JOIN phone ON book.card = phone.card;
EXPLAIN 分析一下sql
ALTER TABLEphoneADD INDEX z( card );
ALTER TABLE'bookADD INDEX Y ( card);#上一個(gè)case建過一個(gè)同樣的
再次EXPLAIN
后⒉行的type都是ref且總rows優(yōu)化很好,效果不錯(cuò)。因此索引最好設(shè)置在需要經(jīng)常查詢的字段中。
【結(jié)論】Join語句的優(yōu)化
盡可能減少Join語句中的NestedLoop的循環(huán)總次數(shù):“永遠(yuǎn)用小結(jié)果集驅(qū)動(dòng)大的結(jié)果集”
優(yōu)先優(yōu)化NestedLoop的內(nèi)層循環(huán);
保證Join語句中被驅(qū)動(dòng)表上Join條件字段已經(jīng)被索引;
當(dāng)無法保證被驅(qū)動(dòng)表的Join條件字段被索引且內(nèi)存資源充足的前提下,不要太吝惜JoinBuffer的設(shè)置;
索引失效(應(yīng)該避免)
建表SQL
CREATE TABLE staffs ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(24)NOT NULL DEFAULT '' COMMENT '姓名', age INT NOT NULL DEFAULT 0 COMMENT '年齡', pos VARCHAR(20)NOT NULL DEFAULT '' COMMENT '職位', add_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入職時(shí)間')CHARSET utf8 COMMENT'員工記錄表';INSERT INTO staffs(NAME,age,pos,add_time)VALUES('z3',22,'manager',NOW()); INSERT INTO staffs(NAME,age,pos,add_time)VALUES('July',23, 'dev',NOW()); INSERT INTO staffs(NAME,age,pos,add_time)VALUES('2000',23,'dev',NOW());SELECT *FROM staffs; # 建立復(fù)合索引 ALTER TABLE staffs ADD INDEX idx_staffs_nameAgePos(NAME, age, pos);案例(索引失效)
查看索引
1.全值匹配我最愛
EXPLAIN SELECT FROM staffs WHERE NAME =July;
EXPLAIN SELECT * FROM staffs WHERE NAME = July AND age = 25;
EXPLAIN SELECTFROM staffs WHERE NAME = July’AND age = 25 AND pos = dev;
2.**最佳左前綴法則**
如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始并且不跳過索引中的列。
只查詢age與pos
只查詢pos
只查詢name
結(jié)論:最佳左前綴法則
如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始并且不跳過索引中的列。
俗話說帶頭大哥不能死,復(fù)合索引的第一個(gè)不能不使用
================================================
那么只查詢name與pos 不要中間的age是否會索引失效呢?
答案是不會
但是由于沒有查詢age,所以子索引age沒有用到,那么就不會用到pos索引,只會用到帶頭的name,因?yàn)閍ge沒有,所以就找不到pos
3.不在索引列上做任何操作(計(jì)算、函數(shù)、(自動(dòng)or手動(dòng))類型轉(zhuǎn)換),會導(dǎo)致索引失效而轉(zhuǎn)向全表掃描
范圍之后全失效
EXPLAIN一下
4.存儲引擎不能使用索引中范圍條件右邊的列
將age=25變成age>25 type由ref變成range,效率下降了
5.盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select *
按需取所要字段
不使用select * 但是age有范圍查詢,效率會高,相比上面第4條案列解釋的sql比較查看
6.mysql在使用不等于(!=或者<>)的時(shí)候無法使用索引會導(dǎo)致全表掃描
7.is null ,is not null也無法使用索引
8.like以通配符開頭('%abc...' )mysql索引失效會變成全表掃描的操作'
使用 %字符串%
使用 %字符串
使用 字符串%
問題:解決like '%字符串%'時(shí)索引不被使用的方法??
建表sql
CREATE TABLE`tbl_user`( `id` INT(11)NOT NULL AUTO_INCREMENT, `name`VARCHAR(20)DEFAULT NULL, `age`INT(11)DEFAULT NULL, email VARCHAR(20) DEFAULT NULL, PRIMARY KEY (id) )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;#drop table tbl_userINSERT INTO tbl_user(NAME,age,email) VALUES('1aa1',21,'b@163.com'); INSERT INTO tbl_user(NAME,age,email)VALUES('2aa2',222, 'a@163.com'); INSERT INTO tbl_user(NAME,age,email)VALUES('3aa3',265,'c@163.com'); INSERT INTO tbl_user(NAME,age,email) VALUES('4aa4',21,'d@163.com');業(yè)務(wù)分析
創(chuàng)建索引
CREATE INDEX idx_user_nameAge ON tbl_user(NAME,age);注意:未建立上方復(fù)合索引前,使用%字符串% 會全表掃描,索引失效
注意:查詢字段為* 的時(shí)候,會導(dǎo)致索引失效
9.字符串不加單引號索引失效
10.少用or,用它來連接時(shí)會索引失效口
11.小總結(jié)
三 查詢截取分析
查詢優(yōu)化
永遠(yuǎn)小表驅(qū)動(dòng)大表 in exists
類似嵌套循環(huán)Nested Loop 嵌套 for循環(huán)
exists
.EXISTS
SELECT … FROM table WHERE EXISTS(subquery)
該語法可以理解為:將主查詢的數(shù)據(jù),放到子查詢中做條件驗(yàn)證,根據(jù)驗(yàn)證結(jié)果(TRUE或FALSE)來決定主查詢的數(shù)據(jù)結(jié)果是否得以保留。
·提示
1 EXSTS (subquery)只返回TRUE或FALSE,因此子查詢中的SELECT*也可以是SELECT 1或 ‘X’,官方說法是實(shí)際執(zhí)行時(shí)會忽略SELECT猜單,因此沒有區(qū)別。
2 EXISTS子查詢的實(shí)際執(zhí)行過程可能經(jīng)過了優(yōu)化而不是我們理解上的逐條對比,如果擔(dān)憂效率問題,可進(jìn)行實(shí)際檢驗(yàn)以確定是否有效率問題。
3 EXISTS子查詢往往也可以用條件表達(dá)式、其他子查詢或者JOIN來替代,何種最優(yōu)需要具體問題具體分析
結(jié)論:
當(dāng)B表的數(shù)據(jù)集必須小于A表的數(shù)據(jù)集時(shí),用in優(yōu)于exists。
當(dāng)A表的數(shù)據(jù)集系小于B表的數(shù)據(jù)集時(shí),用exists優(yōu)于in。
小表驅(qū)動(dòng)大表
使用之前的部門員工表演示 in exists 查詢
ORDER BY關(guān)鍵字優(yōu)化
ORDER BY子句,盡量使用Index方式排序,避免使用FileSort方式排序
建表SQL
CREATE TABLE tblA( #id int primary key not null auto_increment, age lNT, birth TIMESTAMP NOT NULLINSERT INTO tblA(age,birth) VALUES(22,NOW()); INSERT INTO tblA(age,birth) VALUES(23,NOW()); INSERT INTO tblA(age,birth) VALUES(24,NOW());# 創(chuàng)建age birth的復(fù)合索引 CREATE INDEX idx_A_ageBirth ON tblA(age,birth);案例
查詢出來
1 只order by age 使用到了索引,未產(chǎn)生FileSort
2 order by age,birth 使用到了索引,未產(chǎn)生FileSort
3 order by birth 使用到了索引 產(chǎn)生了FileSort
4 order by birth,age 使用到了索引 產(chǎn)生了FileSort , 因?yàn)閯?chuàng)建復(fù)合索引排序?yàn)?age,birth,你反著也會導(dǎo)排序產(chǎn)生FileSort
5 不where 直接order by birth 使用到索引,產(chǎn)生FileSort
6 直接order by age ASC ,birth DESC 會產(chǎn)生FileSort ,因?yàn)槟J(rèn)是ASC 生序的,而案例的birth使用將序排列那么就會導(dǎo)致mysql從新排一次序,那么就會產(chǎn)生FileSort,導(dǎo)致效率變慢
MySQL支持二種方式的排序,FileSort和Index,Index效率高.它指MySQL掃描索引本身完成排序。FileSort方式效率較低。
ORDER BY滿足兩情況,會使用Index方式排序:
ORDER BY語句使用索引最左前列
使用Where子句與Order BY子句條件列組合滿足索引最左前列
盡可能在索引列上完成排序操作,遵照索引建的最佳左前綴
如果不在索引列上,FileSort有兩種算法:
mysql就要啟動(dòng)雙路排序和單路排序
雙路排序
MySQL4.1之前是使用雙路排序,字面意思就是兩次掃描磁盤,最終得到數(shù)據(jù),讀取行指針和orderby列,對他們進(jìn)行排序,然后掃描已經(jīng)排序好的列表,按照列表中的值重新從列表中讀取對應(yīng)的數(shù)據(jù)輸出
從磁盤取排序字段,在buffer進(jìn)行排序,再從磁盤取其他字段。
取一批數(shù)據(jù),要對磁盤進(jìn)行了兩次掃描,眾所周知,I\O是很耗時(shí)的,所以在mysql 4.1之后,出現(xiàn)了第二種改進(jìn)的算法,就是單路排序。
單路排序
從磁盤讀取查詢需要的所有列,按照order by列在buffer對它們進(jìn)行排序,然后掃描排序后的列表進(jìn)行輸出,它的效率更快一些,避免了第二次讀取數(shù)據(jù)。并且把隨機(jī)I0變成了順序IO,但是它會使用更多的空間,因?yàn)樗衙恳恍卸急4嬖趦?nèi)存中了。
結(jié)論及引申出的問題
由于單路是后出的,總體而言好過雙路
但是用單路有問題
在sort_buffer中,方法B比方法A要多占用很多空間,因?yàn)榉椒˙是把所有字段都取出,所以有可能取出的數(shù)據(jù)的總大小超出了sort_buffer的容量,導(dǎo)致每次只能取sort_buffer容量大小的數(shù)據(jù),進(jìn)行排序(創(chuàng)建tmp文件,多路合并),排完再取sort_buffer容量大小,再排……從而多次I/O.
本來想省一次I/O操作,反而導(dǎo)致了大量的lO操作,反而得不償失。
優(yōu)化策略
增大sort_buffer_size參數(shù)的設(shè)置
增大max_length_for_sort_data參數(shù)的設(shè)置
Why 如何提高Order By的速度
1.提高Order By的速度
Order by時(shí)select*是一個(gè)大忌只Query需要的字段,這點(diǎn)非常重要。在這里的影響是:
1.1當(dāng)Query的字段大小總和小于max_length_for_sort_data而且排序字段不是TEXTIBLOB類型時(shí),會用改進(jìn)后的算法——單路排序,否則用老算法——多路排序。
1.2兩種算法的數(shù)據(jù)都有可能超出sort_buffer的容量,超出之后,會創(chuàng)建tmp文件進(jìn)行合并排序,導(dǎo)致多次IO,但是用單路排序算法的風(fēng)險(xiǎn)會更大一些,所以要提高sort_buffer_size。
2.嘗試提高sort_buffer_size
不管用哪種算法,提高這個(gè)參數(shù)都會提高效率,當(dāng)然,要根據(jù)系統(tǒng)的能力去提高,因?yàn)檫@個(gè)參數(shù)是針對每個(gè)進(jìn)程的
3.嘗試提高max_length_for_sort_data
提高這個(gè)參數(shù),會增加用改進(jìn)算法的概率。但是如果設(shè)的太高,數(shù)據(jù)總?cè)萘砍鰏ort_buffer_size的概率就增大,明顯癥狀是高的磁盤I/O活動(dòng)和低的處理器使用率.
小總結(jié)
GROUP BY關(guān)鍵字優(yōu)化
與order by一樣方式優(yōu)化
group by實(shí)質(zhì)是先排序后進(jìn)行分組,遵照索引建的最佳左前綴
當(dāng)無法使用索引列,增大max_length_for_sort_data參數(shù)的設(shè)置+增大sort_buffer_size參數(shù)的設(shè)置
where高于having,能寫在where限定的條件就不要去having限定了。
慢查詢?nèi)罩?/h2>
是什么
MySQL的慢查詢?nèi)罩臼荕ySQL提供的一種日志記錄,它用來記錄在MySQL中響應(yīng)時(shí)間超過閥值的語句,具體指運(yùn)行時(shí)間超過long_query_time值的SQL,則會被記錄到慢查詢?nèi)罩局小?/p>
具體指運(yùn)行時(shí)間超過long_query_time值的SQL,則會被記錄到慢查詢?nèi)罩局小ong _query_time的默認(rèn)值為10,意思是運(yùn)行10秒以上的語句。
由他來查看哪些SQL超出了我們的最大忍耐時(shí)間值,比如一條sql執(zhí)行超過5秒鐘,我們就算慢SQL,希望能收集超過5秒的sql,結(jié)合之前explain進(jìn)行全面分析。
怎么玩
說明
默認(rèn)情況下 MySQL數(shù)據(jù)庫沒有開啟慢查詢?nèi)罩?#xff0c;需要我們手動(dòng)來設(shè)置這個(gè)參數(shù)。
當(dāng)然,如果不是調(diào)優(yōu)需要的話,一般不建議啟動(dòng)該參數(shù),因?yàn)殚_啟慢查詢?nèi)罩緯蚨嗷蛏賻硪欢ǖ男阅苡绊憽B樵內(nèi)罩局С謱⑷罩居涗泴懭胛募?/p>
查看是否開啟及如何開啟
默認(rèn) SHow VARIABLES LIKE ‘%slow_query_log%’;
默認(rèn)情況下slow_query_log的值為OFF,表示慢查詢?nèi)罩臼墙玫?
可以通過設(shè)置slow auery loa的值來開啟
開啟 set global slow_query_log=1;
使用set global slow_query_log=1開啟了慢查詢?nèi)罩局粚Ξ?dāng)前數(shù)據(jù)庫生效,如果MySQL重啟后則會失效。
如果要永久生效,就必須修改配置文件my.cnf(其它系統(tǒng)變量也是如此)
修改my.cnf文件,[mysqld]下增加或修改參數(shù)
slow_query_log和slow_query_log_file后,然后重啟MySQL服務(wù)器。也即將如下兩行配置進(jìn)my.cnf文件
slow_query_log =1
slow_query_log_file=/var/lib/mysql/fs-slow.log
關(guān)于慢查詢的參數(shù)slow_query_log_file,它指定慢查詢?nèi)罩疚募拇娣怕窂?#xff0c;系統(tǒng)默認(rèn)會給一個(gè)缺省的文件host_name-slow.log (如果沒有指定參數(shù)slow_query_log_file的話)
I
一般 不建議 修改my.cnf永久生效,因?yàn)闀ysql的性能有影響
那么開啟了慢查詢?nèi)罩竞?#xff0c;什么樣的SQL才會記錄到慢查詢?nèi)罩纠锩婺?
這個(gè)是由參數(shù)long_query_time控制,默認(rèn)情況下long_query_time的值為10秒,命令:SHOW VARIABLES LIKE ‘long_query_time%’;
可以使用命令修改,也可以在my.cnf參數(shù)里面修改。
假如運(yùn)行時(shí)間正好等于long_query_time的情況,并不會被記錄下來。也就是說,在mysql源碼里是判斷大于long_query_time,而非大于等于。
案例
查看當(dāng)前多少秒算慢
設(shè)置慢的闕值時(shí)間
SHOW VARIABLES LIKE ‘long_query_time%’;
修改為闕值到3秒鐘的就是慢sql
為什么設(shè)置后看不出變化?
需要重新連接或新開一個(gè)會話才能看到修改值。
SHOW VARIABLES LIKE ‘long_query_time%’;
show global variables like ‘long_query_time’;
記錄慢SQL并后續(xù)分析
se1ect sleep(4 );
sleep(4 )命令就是查詢的時(shí)候睡4秒,因?yàn)樵O(shè)置的值為3秒就為慢sql,那么這條sql會被mysql認(rèn)為慢sql
查詢當(dāng)前系統(tǒng)中有多少條慢查詢記錄
show global status like ‘%Slow_queries%’;
配置版
【mysqld】下配置:
slow_query_log=1,
slow query_log_file=/var/lib/mysql/fs-slow.log
long_query_time=3;
log_output=FILE
日志分析工具mysqldumpslow
在生產(chǎn)環(huán)境中,如果要手工分析日志,查找、分析SQL,顯然是個(gè)體力活,MySQL提供了日志分析工具mysqldumpslow。
查看mysqldumpslow的幫助信息
mysqldumpslow --help
s:是表示按照何種方式排序;
c:訪問次數(shù)
l:鎖定時(shí)間
r:返回記錄
t:查詢時(shí)間
al:平均鎖定時(shí)間
ar:平均返回記錄數(shù)
at:平均查詢時(shí)間
t:即為返回前面多少條的數(shù)據(jù);
g:后邊搭配一個(gè)正則匹配模式,大小寫不敏感的;
工作常用參考
從fs.log中
得到返回記錄集最多的10個(gè)SQL
mysqldumpslow -s r-t 10 /var/lib/mysql/fs-slow.log
得到訪問次數(shù)最多的10個(gè)SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/fs-slow.log
得到按照時(shí)間排序的前10條里面含有左連接的查詢語句
mysqldumpslow -s t -t 10 -g “l(fā)eft join” /var/lib/mysql/fs-slow.log
另外建議在使用這些命令時(shí)結(jié)合|和more 使用,否則有可能出現(xiàn)爆屏情況
mysqldumpslow -s r -t 10 /var/lib/mysql/fs-slow.log | more
批量數(shù)據(jù)腳本
往表里插入1000W數(shù)據(jù)
1.建表sql
#新建庫 CREATE DATABASE bigData;USE bigData;#1建表dept CREATE TABLE dept( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, dname VARCHAR(20) NOT NULL DEFAULT"", loc VARCHAR(13)NOT NULL DEFAULT"" )ENGINE=INNODB DEFAULT CHARSET=GBK ;#2建表emp CREATE TABLE emp ( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*編號*/ lename VARCHAR(20)NOT NULL DEFAULT"",/*名字*/ job VARCHAR(9) NOT NULL DEFAULT"",/*工作*/. mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上級編號*/ hiredate DATE NOT NULL,/*入職時(shí)間*/ sal DECIMAL(7,2)NOT NULL,/*薪水*/ comm DECIMAL(7,2)NOT NULL,/*紅利*/ deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0/*部門編號*/) ENGINE=INNODB DEFAULT CHARSET=GBK ;2.設(shè)置參數(shù)log_bin_trust_function_creators
創(chuàng)建函數(shù),假如報(bào)錯(cuò):This function has none of DETERMINISTIC…
#由于開啟過慢查詢?nèi)罩?#xff0c;因?yàn)槲覀冮_啟了bin-log,我們就必須為我們的function指定一個(gè)參數(shù)。
show variables like 'log_bin_trust_function_creators";
set global log_bin_trust_function_creators=1;
#這樣添加了參數(shù)以后,如果mysqld重啟,上述參數(shù)又會消失,永久方法:
windows下my.ini[mysqld]加上log_bin_trust_function_creators=1
linux下letc/my.cnf 下my.cnf[mysqld]加上log_bin_trust_function_creators=1
3.創(chuàng)建函數(shù),保證每條數(shù)據(jù)都不同
隨機(jī)產(chǎn)生字符串
# 返回隨機(jī)字符串的函數(shù) DELIMITER $$ CREATE FUNCTION rand_string(n INT)RETURNS VARCHAR(255) BEGIN DECLARE chars_str VARCHAR(100)DEFAULT'abcdefghijklmnopqarstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ'; DECLARE return_str VARCHAR(255)DEFAULT ''; DECLARE i INT DEFAULT 0; WHILE i<n DO SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1)); SET i= i + 1; END WHILE; RETURN return_str; END $$#假如要?jiǎng)h除 DROP FUNCTION rand_string;隨機(jī)產(chǎn)生部門編號
#用于隨機(jī)產(chǎn)生部門編號 DELIMITER $$ CREATE FUNCTION rand_num() RETURNS INT(5) BEGIN DECLARE i INT DEFAULT 0; SET i = FLOOR(100+RAND()*10); RETURN i; END $$#假如要?jiǎng)h除 DROP FUNCTION rand_num;4.創(chuàng)建存儲過程
創(chuàng)建往emp表中插入數(shù)據(jù)的存儲過程
# 創(chuàng)建往emp表中插入數(shù)據(jù)的存儲過程 DELIMITER $$ CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10)) BEGIN DECLARE i INT DEFAULT 0; #set autocommit =O把a(bǔ)utocommit設(shè)置成0 SET autocommit = 0; REPEAT SET i = i + 1; INSERT INTO emp (empno, lename ,job ,mgr ,hiredate ,sal ,comm ,deptno ) VALUES ((START+i) ,rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num()); UNTIL i = max_num END REPEAT; COMMIT; END $$創(chuàng)建往dept表中插入數(shù)據(jù)的存儲過程
#創(chuàng)建往dept表中插入數(shù)據(jù)的存儲過程 DELIMITER $$ CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10)) BEGIN DECLARE i INT DEFAULT 0; SET autocommit = 0; REPEAT SET i = i + 1; INSERT INTO dept (deptno ,dname,loc ) VALUES ((START+i) ,rand_string(10),rand_string(8)); UNTIL i = max_num END REPEAT; COMMIT; END $$5.調(diào)用存儲過程
dep
# 調(diào)用 DELIMITER的意思就是之前創(chuàng)建函數(shù)與存儲過程的時(shí)候,指定為$$ 開頭結(jié)尾,但是我們已經(jīng)創(chuàng)建完成了,就恢復(fù)為 ; 結(jié)尾SELECT * FROM `dept`DELIMITER; CALL insert_dept(100,10);emp
執(zhí)行存儲過程 ,往emp表添加50萬條數(shù)據(jù)
Show Profile
是什么:
是mysql提供可以用來分析當(dāng)前會話中語句執(zhí)行的資源消耗情況。可以用于SQL的調(diào)優(yōu)的測量
官網(wǎng): http://dev.mysql.com/doc/refman/5.5/en/show-profile.html
默認(rèn)情況下,參數(shù)處于關(guān)閉狀態(tài),并保存最近15次的運(yùn)行結(jié)果
分析步驟
1.是否支持,看看當(dāng)前的mysql版本是否支持
Show variables like ‘profiling’;
默認(rèn)是關(guān)閉,使用前需要開啟
或者:Show variables like ‘profiling%’;
2.開啟功能,默認(rèn)是關(guān)閉,使用前需要開啟
SET profiling=ON;
3.運(yùn)行SQL
select * from emp group by id%10 limit 150000;
select * from emp group by id%20 order by 5;
4.查看結(jié)果,show profiles;
5.診斷SQL,show profile cpu,block io for query 上一步前面的問題SOL數(shù)字號碼:
查詢上面show profile中id為3號的 查參數(shù)字段為 cpu ,block io 這兩個(gè)參數(shù)最常用
show profile cpu ,block io for query 3;
參數(shù)備注
type:
|ALL --顯示所有的開銷信息
| BLOCK IO–顯示塊lO相關(guān)開銷
| CONTEXT SWITCHES --上下文切換相關(guān)開銷| CPU–顯示CPU相關(guān)開銷信息
| lPC–顯示發(fā)送和接收相關(guān)開銷信息
|MEMORY–顯示內(nèi)存相關(guān)開銷信息
|PAGE FAULTS–顯示頁面錯(cuò)誤相關(guān)開銷信息
| SOURCE–顯示和Source_function,Source_file,Source_line相關(guān)的開銷信息
| SWAPS–顯示交換次數(shù)相關(guān)開銷的信息
6.日常開發(fā)需要注意的結(jié)論
出現(xiàn)以下四種,就需要優(yōu)化sql了
一 converting HEAP to MyISAM查詢結(jié)果太大,內(nèi)存都不夠用了往磁盤上搬了。
二 Creating tmp table創(chuàng)建臨時(shí)表
-----------------------------------------------拷貝數(shù)據(jù)到臨時(shí)表
-----------------------------------------------用完再刪除
三 Copying to tmp table on disk把內(nèi)存中臨時(shí)表復(fù)制到磁盤,危險(xiǎn)!
四 locked
查看一下上面2.7秒多的8號sql
show profile all for query 8;
可以看到這個(gè)sql是在copying to tmp 2.5秒,所以sql是有問題的
全局查詢?nèi)罩?/h2>
配置啟用
在mysql的my.cnf中,設(shè)置如下:#開啟
general_log=1
#記錄日志文件的路徑
general_log_file=/path/logfile
#輸出格式
log_output=FILE
編碼啟用
命令
set global general_log=1;
set global log_output=‘TABLE’;
此后,你所編寫的sql語句,將會記錄到mysql庫里的general_log表,可以用下面的命令查看
select * from mysql.general_log;
永遠(yuǎn)不要在生產(chǎn)環(huán)境開啟這個(gè)功能。
四 MySql鎖機(jī)制
概述
定義
鎖是計(jì)算機(jī)協(xié)調(diào)多個(gè)進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制。
在數(shù)據(jù)庫中,除傳統(tǒng)的計(jì)算資源(如CPU、RAM、/O等〉的爭用以外,數(shù)據(jù)也是一種供許多用戶共享的資源。如何保證數(shù)據(jù)并發(fā)訪問的一致性、有效性是所有數(shù)據(jù)庫必須解決的一個(gè)問題,鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個(gè)重要因素。從這個(gè)角度來說,鎖對數(shù)據(jù)庫而言顯得尤其重要,也更加復(fù)雜。
生活購物 打比方 秒殺
打個(gè)比方,我們到淘寶上買一件商品,商品只有一件庫存,這個(gè)時(shí)候如果還有另一個(gè)人買,那么如何解決是你買到還是另一個(gè)人買到的問題?
這里肯定要用到事務(wù),我們先從庫存表中取出物品數(shù)量,然后插入訂單,付款后插入付款表信息,然后更新商品數(shù)量。在這個(gè)過程中,使用鎖可以對有限的資源進(jìn)行保護(hù),解決隔離和并發(fā)的矛盾。
鎖的分類
從對數(shù)據(jù)操作的類型(讀\寫)分
讀鎖(共享鎖):針對同一份數(shù)據(jù),多個(gè)讀操作可以同時(shí)進(jìn)行而不會互相影響。
寫鎖(排它鎖):當(dāng)前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖。
從對數(shù)據(jù)操作的粒度分
表鎖
行鎖
三鎖
表鎖(偏讀)
特點(diǎn)
偏向MyISAM存儲引擎,開銷小,加鎖快;無死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。
案例分析
建表sql
#【表級鎖分析-建表SQL】 CREATE TABLE mylock( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) )ENGINE MYISAM;INSERT INTO mylock(NAME) VALUES('a'); INSERT INTO mylock(NAME) VALUES('b'); INSERT INTO mylock(NAME) VALUES('c'); INSERT INTO mylock(NAME) VALUES('d'); INSERT INTO mylock(NAME) VALUES('e');SELECT * FROM mylock;【手動(dòng)增加表鎖】
lock table 表名字 read(write),表名字2 read(write),其它;
【查看表上加過的鎖】
show open tab1es;
發(fā)現(xiàn)表中都沒用鎖
給mylock表加讀鎖給book表加寫鎖
lock table mylock read , book write ;
解鎖
unlock tables ;
加讀鎖 案例演示
1.會話1 mylock加讀鎖,會話1,2分別查詢mylock表
2.會話1 mylock加讀鎖,會話1更新mylock表
3.會話1 mylock加讀鎖, 會話1 查詢其他表
4.會話1 mylock加讀鎖, 會話2 更新mylock表
會話1 unlock 解鎖
加寫鎖 案例演示
首先 unlock tables;
會話1 給mylock 加寫鎖
會話1 unlock tables;
案例結(jié)論
MyISAM在執(zhí)行查誨語句(SELECT)前,會自動(dòng)給涉及的所有表加讀鎖,在執(zhí)行增刪改操作前,會自動(dòng)給涉及的表加寫鎖。MySQL的表級鎖有兩種模式:
表共享讀鎖(Table Read Lock)
表獨(dú)占寫鎖(Table Write Lock)
結(jié)論:
結(jié)合上表,所以對MyISAM表進(jìn)行操作,會有以下情況:
1、對MyISAM表的讀操作(加讀鎖),不會阻塞其他進(jìn)程對同一表的讀請求,但會阻塞對同一表的寫請求。只有當(dāng)讀鎖釋放后,才會執(zhí)行其它進(jìn)程的寫操作。
2、對MylSAM表的寫操作(加寫鎖),會阻塞其他進(jìn)程對同一表的讀和寫操作,只有當(dāng)寫鎖釋放后,才會執(zhí)行其它進(jìn)程的讀寫操作
簡而言之,就是讀鎖會阻塞寫,但是不會堵塞讀。而寫鎖則會把讀和寫都堵塞
表鎖分析
【看看哪些表被加鎖了】
mysql>show open tables;
【如何分析表鎖定】
可以通過檢查 table_locks_waited 和 table_locks_immediate 狀態(tài)變量來分析系統(tǒng)上的表鎖定:SQL:
show status like ‘table%’;
這里有兩個(gè)狀態(tài)變量記錄MySQL內(nèi)部表級鎖定的情況,兩個(gè)變量說明如下:
Table_locks_immediate:產(chǎn)生表級鎖定的次數(shù),表示可以立即獲取鎖的查詢次數(shù),每立即獲取鎖值加1;
Table_locks_waited:出現(xiàn)表級鎖定爭用而發(fā)生等待的次數(shù)(不能立即獲取鎖的次數(shù),每等待一次鎖值加1),此值高則說明存在著較嚴(yán)重的表級鎖爭用情況;
此外,Myisam的讀寫鎖調(diào)度是寫優(yōu)先,這也是myisam不適合做寫為主表的引擎。因?yàn)閷戞i后,其他線程不能做任何操作,大量的更新會使查詢很難得到鎖,從而造成永遠(yuǎn)阻塞
行鎖(偏寫)
特點(diǎn):
InnoDB存儲引擎,開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。
InnoDB與MyISAM的最大不同有兩點(diǎn):
一是支持事務(wù)(TRANSACTION);
二是采用了行級鎖
由于行鎖支持事務(wù),事務(wù)知識點(diǎn)概念
事務(wù)( Transaction)及其ACID屬性
事務(wù)是由一組SQL語句組成的邏輯處理單元,事務(wù)具有以下4個(gè)屬性,通常簡稱為事務(wù)的ACID屬性。
l原子性(Atomicity):事務(wù)是一個(gè)原子操作單元,其對數(shù)據(jù)的修改,要么全都執(zhí)行,要么全都不執(zhí)行。
l一致性(Consistent):在事務(wù)開始和完成時(shí),數(shù)據(jù)都必須保持一致狀態(tài)。這意味著所有相關(guān)的數(shù)據(jù)規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持?jǐn)?shù)據(jù)的完整性;事務(wù)結(jié)束時(shí),所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如B樹索引或雙向鏈表)也都必須是正確的。
l隔離性(lsolation):數(shù)據(jù)庫系統(tǒng)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的“獨(dú)立”環(huán)境執(zhí)行。這意味著事務(wù)處理過程中的中間狀態(tài)對外部是不可見的,反之亦然。
l持久性(Durable):事務(wù)完成之后,它對于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。
并發(fā)事務(wù)處理帶來的問題
更新丟失(Lost Update)
當(dāng)兩個(gè)或多個(gè)事務(wù)選擇同一行,然后基于最初選定的值更新該行時(shí),由于每個(gè)事務(wù)都不知道其他事務(wù)的存在,就會發(fā)生丟失更新問題――最后的更新覆蓋了由其他事務(wù)所做的更新。
例如,兩個(gè)程序員修改同一java文件。每程序員獨(dú)立地更改其副本,然后保存更改后的副本,這樣就覆蓋了原始文檔。最后保存其更改副本的編輯人員覆蓋前一個(gè)程序員所做的更改。
如果在一個(gè)程序員完成并提交事務(wù)之前,另一個(gè)程序員不能訪問同一文件,則可避免此問題。
臟讀(Dirty Reads)
一個(gè)事務(wù)正在對一條記錄做修改,在這個(gè)事務(wù)完成并提交前,這條記錄的數(shù)據(jù)就處于不一致狀態(tài);這時(shí),另一個(gè)事務(wù)也來讀取同一條記錄,如果不加控制,第二個(gè)事務(wù)讀取了這些“臟”數(shù)據(jù),并據(jù)此做進(jìn)一步的處理,就會產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被形象地叫做”臟讀”。
一句話:事務(wù)A讀取到了事務(wù)B已修改但尚未提交的的數(shù)據(jù),還在這個(gè)數(shù)據(jù)基礎(chǔ)上做了操作。此時(shí),如果B事務(wù)回滾,A讀取的數(shù)據(jù)無效,不符合一致性要求。
不可重復(fù)讀(Non-Repeatable Reads)
一個(gè)事務(wù)在讀取某些數(shù)據(jù)后的某個(gè)時(shí)間,再次讀取以前讀過的數(shù)據(jù),卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變、或某些記錄已經(jīng)被刪除了!這種現(xiàn)象就叫做“不可重復(fù)讀”。
一句話:事務(wù)A讀取到了事務(wù)B已經(jīng)提交的修改數(shù)據(jù),不符合隔離性
幻讀(Phantom Reads)
一個(gè)事務(wù)按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為“幻讀
一句話:事務(wù)A讀取到了事務(wù)B提交的新增數(shù)據(jù),不符合隔離性。
多說一句:幻讀和臟讀有點(diǎn)類似,
臟讀是事務(wù)B里面修改了數(shù)據(jù),幻讀是事務(wù)B里面新增了數(shù)據(jù)。
事務(wù)隔離級別
臟讀”、“不可重復(fù)讀”和“幻讀”,其實(shí)都是數(shù)據(jù)庫讀一致性問題,必須由數(shù)據(jù)庫提供一定的事務(wù)隔離機(jī)制來解決。
數(shù)據(jù)庫的事務(wù)隔離越嚴(yán)格,并發(fā)副作用越小,但付出的代價(jià)也就越大,因?yàn)槭聞?wù)隔離實(shí)質(zhì)上就是使事務(wù)在一定程度上“串行化”進(jìn)行,這顯然與“并發(fā)”是矛盾的。同時(shí),不同的應(yīng)用對讀一致性和事務(wù)隔離程度的要求也是不同的,比如許多應(yīng)用對“不可重復(fù)讀”和“幻讀”并不敏感,可能更關(guān)心數(shù)據(jù)并發(fā)訪問的能力。
常看當(dāng)前數(shù)據(jù)庫的事務(wù)隔離級別: show variables like ‘tx_isolation’;
案例分析
建表SQL
CREATE TABLE test_innodb_lock (a INT(11),b VARCHAR(16))ENGINE=INNODB; INSERT INTO test_innodb_lock VALUES(1,'b2'); INSERT INTO test_innodb_lock VALUES(3,'3'); INSERT INTO test_innodb_lock VALUES(4,'4000'); INSERT INTO test_innodb_lock VALUES(5,'5000'); INSERT INTO test_innodb_lock VALUES(6,'6000'); INSERT INTO test_innodb_lock VALUES(7,'7000'); INSERT INTO test_innodb_lock VALUES(8,'8000'); INSERT INTO test_innodb_lock VALUES(9,'9000'); INSERT INTO test_innodb_lock VALUES(1,'b1');# 建立索引 CREATE INDEX test_innodb_a_ind ON test_innodb_lock(a); CREATE INDEX test_innodb_lock_b_ind ON test_innodb_lock(b);行鎖定基本演示
先 set autocommit = 0 ;關(guān)閉事物的自動(dòng)提交
會話1 更新數(shù)據(jù),會話1 查看 會話2 查看
結(jié)論:讀己之所寫(只能讀自己更新的數(shù)據(jù))
會話1 2 都commit一下后,就能查看到更新的數(shù)據(jù)了
會話1 更新a=4這一行 未commit 會話2也來更新a=4這一行
會話1 2 commit;
會話1 更新a=4 會話2 更新a=9 會不會阻塞?
補(bǔ)充:
因?yàn)閙ysql的默認(rèn)機(jī)制是 可重復(fù)讀 ,會話1 2 都取消自動(dòng)提交了,當(dāng)會話1 更新后并且comment,會話2是查看不到會話1更新后的數(shù)據(jù),因?yàn)殛P(guān)閉了自動(dòng)提交,而且是重復(fù)讀,但是:若新建立一個(gè)會話3 ,會話3 默認(rèn)為自動(dòng)提交,那么會話1 更新后并且comment,會話3能夠立馬查看到會話1的更新數(shù)據(jù)
無索引行鎖升級為表鎖
會話 1 更新語句索引失效 ,未comment ,會話2再次更新
會話1 comment
間隙鎖危害
【什么是間隙鎖】
當(dāng)我們用范圍條件而不是相等條件檢索數(shù)據(jù),并請求共享或排他鎖時(shí),InnoDB會給符合條件的已有數(shù)據(jù)記錄的索引項(xiàng)加鎖;對于鍵值在條件范圍內(nèi)但并不存在的記錄,叫做“間隙(GAP)”,
InnoDB也會對這個(gè)“間隙”加鎖,這種鎖機(jī)制就是所謂的間隙鎖(Next-Key鎖)
【危害】
因?yàn)镼uery執(zhí)行過程中通過過范圍查找的話,他會鎖定整個(gè)范圍內(nèi)所有的索引鍵值,即使這個(gè)鍵值并不存在。
間隙鎖有一個(gè)比較致命的弱點(diǎn),就是當(dāng)鎖定一個(gè)范圍鍵值之后,即使某些不存在的鍵值也會被無辜的鎖定,而造成在鎖定的時(shí)候無法插入鎖定鍵值范圍內(nèi)的任何數(shù)據(jù)。在某些場景下這可能會對性能造成很大的危害
會話1 更新1<a<6 范圍內(nèi)的會產(chǎn)生間隙鎖
面試題:常考如何鎖定一行
當(dāng)查詢某一行的時(shí)候,在 sql 尾部加上for update;就給這一行上行鎖了
案列結(jié)論
Innodb存儲引擎由于實(shí)現(xiàn)了行級鎖定,雖然在鎖定機(jī)制的實(shí)現(xiàn)方面所帶來的性能損耗可能比表級鎖定會要更高一些,但是在整體并發(fā)處理能力方面要遠(yuǎn)遠(yuǎn)優(yōu)于MyISAM的表級鎖定的。當(dāng)系統(tǒng)并發(fā)量較高的時(shí)候,Innodb的整體性能和MyISAM相比就會有比較明顯的優(yōu)勢了。
但是,Innodb的行級鎖定同樣也有其脆弱的一面,當(dāng)我們使用不當(dāng)?shù)臅r(shí)候,可能會讓Innodb的整體性能表現(xiàn)不僅不能比MyYISAM高,甚至可能會更差。
行鎖分析
【如何分析行鎖定】
通過檢查InnoDB_row_lock狀態(tài)變量來分析系統(tǒng)上的行鎖的爭奪情況
show status like 'innodb_row_lock%';
對各個(gè)狀態(tài)量的說明如下:
Innodb_row_lock_current_waits:當(dāng)前正在等待鎖定的數(shù)量;
Innodb_row_lock_time:從系統(tǒng)啟動(dòng)到現(xiàn)在鎖定總時(shí)間長度;
Innodb_row_lock_time_avg:每次等待所花平均時(shí)間;
Innodb_row_lock_time_max:從系統(tǒng)啟動(dòng)到現(xiàn)在等待最常的一次所花的時(shí)間;
Innodb_row_lock_waits:系統(tǒng)啟動(dòng)后到現(xiàn)在總共等待的次數(shù);
對于這5個(gè)狀態(tài)變量,比較重要的主要是
優(yōu)化建議
盡可能讓所有數(shù)據(jù)檢索都通過索引來完成,避免無索引行鎖升級為表鎖。
合理設(shè)計(jì)索引,盡量縮小鎖的范圍
盡可能較少檢索條件,避免間隙鎖
盡量控制事務(wù)大小,減少鎖定資源量和時(shí)間長度
盡可能低級別事務(wù)隔離
頁鎖
了解一下即可
開銷和加鎖時(shí)間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。
這三種鎖 開銷、加鎖速度、死鎖、粒度、并發(fā)性能只能就具體應(yīng)用的特點(diǎn)來說哪種鎖更合適
五 主從復(fù)制
復(fù)制的基本原理
slave會從master讀取binlog來進(jìn)行數(shù)據(jù)同步
三步驟+原理圖
MySQL復(fù)制過程分成三步:
1 master將改變記錄到二進(jìn)制日志(binary log)。這些記錄過程叫做二進(jìn)制日志事件,binary log events;
2 slave將master的binary log events拷貝到它的中繼日志(relay log) ;
3 slave重做中繼日志中的事件,將改變應(yīng)用到自己的數(shù)據(jù)庫中。MySQL復(fù)制是異步的且串行化的
復(fù)制的基本原則
每個(gè)slave只有一個(gè)master
每個(gè)slave只能有一個(gè)唯一的服務(wù)器ID
每個(gè)master可以有多個(gè)salve
復(fù)制的最大問題
延時(shí)
一主一從常見配置
mysql版本一致且后臺以服務(wù)運(yùn)行
主從都配置在[mysqld]結(jié)點(diǎn)下,都是小寫
主機(jī)修改my.ini配置文件
從機(jī)修改my.cnf配置文件
[必須]從服務(wù)器唯一ID
[可選]啟用二進(jìn)制日志
因修改過配置文件,請主機(jī)+從機(jī)都重啟后臺mysql服務(wù)
主機(jī)從機(jī)都關(guān)閉防火墻
windows手動(dòng)關(guān)閉
關(guān)閉虛擬機(jī)linux防火墻service iptables stop
在Windows主機(jī)上建立帳戶并授權(quán)slave
在Linux從機(jī)上配置需要復(fù)制的主機(jī)
主機(jī)新建庫、新建表、insert記錄,從機(jī)復(fù)制
如何停止從服務(wù)復(fù)制功能
stop slave;
總結(jié)
以上是生活随笔為你收集整理的学习笔记之-MySql高级之sql优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM学习笔记之-垃圾回收相关概念 Sy
- 下一篇: 学习笔记之-java8的新特性-函数式接