8四、MySQL強化

索引:幫助MySQL提升獲取數據的數據結構,換一句話講就是「排好序的快速查找的數據結構」。java

索引的分類:一、普通索引;二、惟一索引;三、主鍵索引;四、組合索引;五、全文索引mysql

 

普通索引:是最基本的索引,他沒有任何限制程序員

惟一索引:與普通索引相似,不一樣的就是索引的值必須惟一,但容許有空值。若是是組合索引,則列值的組合必須惟一sql

主鍵索引:是一種特殊的惟一索引,一個表只能有一個主鍵,不容許有空值數據庫

注意:主鍵必惟一,惟一不必定是主鍵express

組合索引:一個索引包含多個列,實際開發中推薦使用複合索引緩存

複合索引的特色:若是咱們建立了(name,age,xb)的複合索引,那麼其實至關於建立了(name,age,xb);(name,age);(name)三個索引,這被稱爲最佳左前綴特性。所以咱們在建立複合索引時,應該將最經常使用做限制條件的列放在最左邊,依次遞減。服務器

全文索引:全文搜索索引,FULLTEXT用於搜索很長的一篇文章的時候,效果最好,用在比較短的文本,若是就一兩行字的,普通的INDEX也能夠session

 

使用索引的優勢:數據結構

一、提升數據檢索的效率,下降數據庫IO的成本

二、經過索引對數據進行排序,下降數據的排序成本,下降CPU的消耗

使用索引的缺點:

一、當對錶中的數據進行增長,刪除和修改的時候,索引也要動態的維護,這樣就下降了數據的維護速度

二、索引須要佔用物理空間,除了數據表佔數據空間以外,每個索引還要佔用必定的物理空間,若是創建聚簇索引,那麼須要的空間就會更大

 

何時須要建立索引:

一、主鍵自動建立惟一索引

二、較頻繁的做爲查詢條件的字段

三、查詢中排序字段,統計字段,分組字段

何時不須要建立索引
一、表記錄太少的字段

二、常常增刪改的字段

三、惟一性太差的字段,不適合單首創建索引,即便頻繁做爲查詢條件,例如:性別,民族等

 

索引的優化

一、儘可能少使用迷糊查詢,若是要使用那麼通配符%能夠出如今結尾,不能出如今開頭

二、or會引發全表掃描

三、不要使用NOT、!=

四、儘可能少使用select*,而是根據需求來算賬須要顯示的字段

五、縮索引不會包含要NULL值的列

六、不要在列上進行運算,這將致使索引失效而進行全表掃描

七、使用短索引

八、union並不比or的執行效率高

 

MYSQL索引方式:Hash和Btree,通常使用Btree

 

——————————————————————————————————————————————————————————————————————

 

explain:關鍵字,能夠模擬優化器執行SQL語句查詢,從而知道MYSQL如何處理你的SQL語句,分析語句的性能的瓶頸

執行後各字段的含義:

id:select查詢的序列號,包含一組能夠重複的數字,表示查詢中執行SQL語句的順序,通常有三種狀況:

一、id所有相同,sql的執行順序是由上至下的

二、id所有不一樣,sql的執行順序是根據ID大的優先執行

三、id即存在相同,也存在不一樣,先根據id大的優先執行,在根據id相同的從上至下執行

 

select_type

一、simple:簡單的select查詢,查詢中不包含子查詢或者union

二、primary:查詢中若包含任何複雜的子查詢,最外層查詢則被標記爲pirmary

三、subquery:在select或where列表中包含了子查詢

四、derived:在from列表中包含的子查詢被標記爲derived,MySQL會遞歸執行這些子查詢,把結果放在臨時表裏

五、union:若第二個select出如今union以後,則被標記爲union,若union包含在from子句的子查詢中,外層select將被標記爲derived

六、union result:從union表獲取結果的select

 

type,這是一個很是重要的參數,性能從最優到最差的排序:system>const>eq_ref>ref>range>index>all,對Java程序員來講,若保證查詢至少達到range級別或者最好達到ref則算是一個優秀又復負責的程序員

一、 all,全表掃描。全表掃描無疑是最差,如果百萬千萬級別數據量,全表掃描會很是慢

二、index,索引全表掃描。全索引文件掃描比all好不少,畢竟從索引樹中找數據,比從全表中找數據要快

三、range:索引範圍掃描。只檢索給定範圍的行,使用索引來匹配行,範圍縮小了,固然比全表掃描和全索引文件掃描要快。sql語句中通常會有between,in,>,<等查詢

四、ref:非惟一性索引掃描,本質上也是一種索引訪問,返回全部匹配某個單獨值的行。好比查詢公司全部屬於研發團隊的同時,匹配的結果是多個並不是惟一值

五、eq_ref:惟一性索引掃描,對於每一個索引鍵,表中有一條記錄與之匹配

六、const:表示經過索引一次就能夠找到,const用於比較primary key或者union索引

七、system:表中只有一條記錄

 

possible_keys :顯示查詢語句可能用到的索引,不必定被查詢實際使用,僅供參考

 

key:顯示查詢語句實際使用的索引,若爲null,則表示沒有使用索引,

 

key_len:顯示索引中使用的字節數,能夠經過key_len計算查詢中使用的索引長度。在不計損失精確性的狀況下索引長度越短越好。另外,key_len只計算where條件用到的索引長度,而排序和分組就算用到了索引,也不會計算在內

 

ref:若是是使用的常數等值查詢,這裏只會顯示const,若是是鏈接查詢,被驅動表等執行計劃這裏會顯示驅動表等關聯字段,若是是條件使用了表達式或者函數,或者條件列發生了內部隱式轉換,這裏可能顯示爲func

 

rows:這裏是執行計劃中估算的掃描行數,不是精確值,值越大越很差

 

extra:

一、Using filesort:說明MYSQL會對數據使用一個外部的索引排序,二不是按照表內的索引順序進行讀取。MYSQL中沒法利用索引完成的排序稱爲文件排序。出現這個就要馬上優化sql

二、Using temporary:使用了臨時表保存中間結果,MYSQL在對查詢結婚排序時使用臨時表。常見於排序order by和分組查詢group by。出現這個更要馬上優化sql

三、Using index:表示相應的select操做中使用覆蓋縮影,避免訪問了表的數據行,效果不錯!若是同時出現Using where,代表索引被用來執行索引鍵值的查找,若是沒有同時出現Using where,表示索引用來讀取數據而非執行查找動做

四、Using index condition:在5.6版本後加入的特性,優化器會在索引存在的狀況下,經過複合RANGE範圍的條數和總數的比例來選擇進行索引仍是進行全表遍歷

五、Using where:代表使用了where過濾

六、Using join buffer:代表使用鏈接緩存

七、impossible where:where語句的值老是false,不可用,不能用來獲取任何元素

八、distinct:優化distinct操做,在找到第一匹配的元組後即中止找一樣值的動做

 

filtered:一個百分比的值,和rows列的值一塊兒使用,能夠估算出查詢執行計劃中的前一個表的結果集,從而肯定join操做的循環次數,小表驅動大表,減輕鏈接的次數

補充:覆蓋索引,就是select的數據列只用蔥索引中就可以取得,沒必要讀取數據行。

 

優化點:

一、range類型查詢字段後面的索引全都無效

二、左鏈接索引建在右表,右鏈接索引建在左表

三、小表驅動大表,即小的數據集驅動大的數據集,若是是exists,那麼之外表爲驅動表,若是是IN,那麼先執行子查詢。

四、用not exists任何狀況下都比 not in 快

——————————————————————————————————————————————————————————————————————

 

慢查詢:開啓慢查詢日誌,可讓MYSQL記錄下查詢超過指定時間的語句,經過定位分析性能的瓶頸,才能更好的優化數據庫系統的性能

參數:

一、slow_query_log:慢查詢開啓

二、slow_query_log_file:慢查詢日誌存放的位置

三、long_query_time:查詢超過多少秒才記錄

 

配置:全局變量配置,配置文件配置

總結:

一、經過全局變量配置好後,須要關閉會話後從新打開查詢纔有效,經過配置文件須要重啓MySql服務器纔有效

二、由於開啓慢查詢會影響性能,通常建議經過全局變量配置,這樣重啓服務器又是默認關閉慢查詢狀態

 

——————————————————————————————————————————————————————————————————————

 

鎖:數據庫鎖定機制簡單來講,就是數據庫爲了保證數據的一致性,而使各類共享資源在被併發訪問變得有序所設計的一種規則。對於任何一種數據庫來講都須要有相應的鎖定機制

MYSQL各存儲引擎使用了三種類型的鎖定機制:表級鎖定,行級鎖定,頁級鎖定

表級鎖:開銷小,加鎖快,不會出現死鎖;鎖定粒度大,

行級鎖:開銷大,加鎖慢,會出現死鎖;鎖定粒度小,發生鎖衝突的機率最低,併發度也最高

頁面鎖:開銷和加鎖時間介於表鎖和行鎖之間,會出現死鎖,鎖定粒度介於表鎖和行鎖之間,併發度通常

補充:死鎖是指兩個或兩個以上的進程在執行過程當中,由於爭奪資源而形成的一種相互等待的現象,若無外力做用,它們都將沒法推動下去,此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在相互等待的進程稱爲死鎖進程。

 

MySQL的表級鎖MyISAM

MySQL表級鎖有兩種模式:表共享鎖(讀鎖)和表獨佔鎖(寫鎖)。

MyISAM在執行查詢語句(SELECT)前,會自動給涉及的全部表加讀鎖,在執行更新操做(UPDATE,DELECT,INSERT等)前,會自動給涉及的表加寫鎖。讀鎖會阻塞寫,可是不會阻塞讀,而寫鎖則會把讀和寫都堵塞。

針對表鎖的優化:

1)儘可能減小大的複雜的Query,將複雜的Query分拆成幾個小的Query分步進行

2)儘量的創建足夠高效的索引,讓數據檢索更迅速

3)儘可能讓MyISAM存儲引擎的表存放必要的信息,控制字段類型

4)利用合理的機會優化MyISAM表數據文件

 

MySQL行鎖InnoDB

InnoDB與MyISAM的最大不一樣有兩點:一是支持事務,二是採用行級鎖。

 

事務是由一組SQL語句組成的邏輯處理單元,事務具備4個屬性

原子性:事務是一個不可分割的工做單位,事務中的操做要麼都發生,要麼都不發生

一致性:事務結束後,不管事務是否執行成功,數據庫仍然是一個完整性狀態

隔離性:多個用戶併發訪問數據庫時,一個用戶的事務不能被其餘用戶的事務所幹擾,多個併發事務之間數據要相互隔離

持久性:一個事務一旦被提交,它對數據庫中的數據的改變是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響

 

併發事務帶來的問題

更新丟失:當兩個或多個事務選擇同一行,而後基於最初選定的值更新該行時,因爲每一個事務都不知道其餘事務的存在,就會發生丟失更新問題,最後的更新覆蓋了其餘事務所作的更新

髒讀:事務A讀取了事務B更新的數據,而後B回滾操做,那麼A讀取到的數據就是髒數據

不可重複讀:事務A屢次讀取同一個數據,事務B在事務A屢次讀取的過程當中,對數據做了更新並提交,致使事務A屢次讀取同一個數據時,結果不一致

幻讀:系統管理員A將數據庫中全部學生的成績從具體分數改成ABCDE等級,可是系統管理員B就在這個時候插入一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺同樣,就叫幻讀

 

事務隔離級別

一、讀未提交

二、不可重複讀

三、可重複讀

四、串行化

 

InnoDB行鎖是經過索引上的索引項加鎖來實現的,這一點MySQL與Oracle不一樣,後者是經過在數據塊中對相應的數據行加鎖來實現的,因此只有經過索引條件檢索數據,InnoDB才使用行級鎖,不然,InnoDB將使用表鎖

InnoDB實現行鎖類型:

共享鎖:容許一個事務去讀一行,阻止其餘事務得到相同數據集的排他鎖

排他鎖:容許獲取排他鎖的事務更新數據,阻止其餘事務取得相同數據集的共享鎖和排他鎖

 

優化點:

1)儘量讓全部數據都經過索引來完成,避免無索引,行鎖升表鎖

2)合理設計索引,儘可能縮小鎖的範圍

3)儘量減小檢索條件,避免間隙鎖

4)儘可能控制事務大小,減小鎖定資源量和時間

補充:間隙鎖:當咱們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據的索引項加鎖,對於鍵值在條件範圍內,但並不存在的記錄叫間隙。

 

——————————————————————————————————————————————————————————————————————

變量的分類:

系統變量:

一、全局變量

二、會話變量

自定義變量:

一、用戶變量

二、局部變量

 

系統變量:變量由系統定義,不是用戶定義,屬於服務器層面

注意:全局變量須要添加global關鍵字,會話變量須要添加session關鍵字,若是不寫,默認會話級別

全局變量:針對於全部會話有效,但不能跨重啓

會話變量:針對當前會話有效

 

自定義變量:變量由用戶自定義,而不是系統提供的

用戶變量:針對於當前會話有效,做用域同與會話變量

局部變量:僅僅在定義它的begin end塊中有效,應用在begin end中的第一句話

SET @m=1;
SET @n=1;
SET @sum=@m+@n
SELECT @sum

DECLARE m INT DEFAULT 1;
DECLARE n INT DEFAULT 1;
DECLARE sum INT;
SET sum=m+n;
SELECT sum;

 

——————————————————————————————————————————————————————————————————————

 

存儲過程:簡單說就是一組SQL語句集,功能強大,能夠實現一些比較複雜的邏輯功能,相似於java語言中的方法

補充:存儲過程跟觸發器有點相似,都是一組SQL集,可是存儲過程是主動調用的,且功能比觸發器更增強大,觸發器是某件事觸發後自動調用。

優勢:

一、提升代碼的重用性

二、簡化操做

三、減小編譯次數而且減小和數據庫服務器的鏈接次數,提升效率

 

delimlter做用域是會話級別的,當你設置了 delimlter $,那麼在當前會話級別都是變成以$結束

 

存儲過程語法:

一、建立

CREATE PROCEDURE 存儲過程名(參數列表)

BEGIN

    存儲過程

END

 

二、參數

參數模式 參數名 參數類型

參數模式:

in:該參數能夠做爲輸入,也就是該參數須要調用方法入值

out:該參數能夠做爲輸出,也就是該參數能夠做爲返回值

inout:該參數便可以做爲輸入又能夠做爲輸出,也就是該參數即須要傳入值,又能夠返回值

 

三、調用

call 存儲過程名 (實參列表)

 

四、刪除

drop procedure if exies 存儲過程名

注意:存儲過程體中的每條SQL語句的結尾要求必須加分號,若是存儲過程體僅僅只有一句話,begin end能夠省略,存儲過程的結尾使用delimiter從新設置

示例

DELIMITER $
CREAT PROCEDURE myp()
BEGIN
  INSERT INTO admin(username,'password') VALUES ('lily','0000')
END $

 

流程控制結構

條件結構:

if語句

一、if函數

if(條件,值1,值2)

二、if結構

IF expression THEN

    statements;

ELSEIF expression THEN

    statements;

ELSE

    statement;

END IF;

 

case語句

case 變量或表達式

when 值1 then 語句1

when 值2 then 語句2

else 語句n

end

或者

case 

when 條件1 then 語句1

when 條件2 then 語句2

else 語句n

end

 

循環結構:

iterate:相似於continue,繼續,結束本次循環,繼續下一次

leave:相似於break,跳出,結束當前所在的循環

 

whlie:先判斷後執行

【標籤:】whlie 循環條件 do

    循環體;

end while 【標籤】;

 

repeat:先執行後判斷

【標籤:】repeat

    循環體;

until 結束循環條件

end repeat 【標籤】;

 

loop:簡單死循環

【標籤:】loop

    循環體;

end loop 【標籤】;

————————————————————————————————————————————————————————————————————-—

 

遊標:一個存儲在mysql服務器上的數據庫查詢,它不是一條select語句,而是被該語句所檢索出來的結果集

 

使用遊標:

一、聲明遊標:這個過程實際上上沒有遍歷數據的,它只是定義要使用的select語句來獲取數據

二、打開遊標:上面定義好後,那麼這裏就須要打開遊標。這個過程用前面定義的select語句把數據實際檢索出來。即這個步驟以後,咱們就能夠遍歷遊標中的數據了

三、遍歷數據:對於有數據的遊標,根據須要取出各行的數據來進行必定的操做

四、關閉遊標:使用完遊標後,必定要關閉遊標

 

遊標語法:

一、聲明遊標

DECLARE cursor_name CURSOR FOR select_statement;

二、打開遊標

OPEN cursor_name;

三、遍歷數據

FETCH cursor_name INTO  var_name;

四、關閉遊標

CLOSE cursor_name

 

補充:在Mysql中,形成遊標溢出時會引起mysql預約義的NOT FOUND錯誤,因此在上面使用下面的代碼指定了當引起not found錯誤時,定義一個continue的事件,指定這個事件發生時修改變量值

DECLARE continue HANDLER for not found set done = true

 —————————————————————————————————————————————————————————————————————

自定義函數:自定義函數和存儲過程仍是很是類似的,其餘的能夠認爲和存儲過程是同樣的,好比含義,優勢均可以按存儲過程的優勢來理解。它們惟一不一樣點在於:

存儲過程:能夠有0個返回,也能夠有多個返回,適合做批量插入、批量更新

函數:有且僅有一個返回,適合作處理數據後返回一個結果

 

語法:

一、建立函數

CREATE FUNCTION 函數名(參數列表) RETURNS 返回類型

BEGIN 

    函數體

END

二、調用函數

SELECT  函數名(參數列表)

三、查看函數

SHOW FUNCTION STATUS

四、刪除函數

DROP FUNCTION IF EXISTS function_name;

相關文章
相關標籤/搜索