索引:幫助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;