日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

学习笔记之-MySql高级之sql优化

發(fā)布時(shí)間:2024/4/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 学习笔记之-MySql高级之sql优化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一 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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。