MySQL-索引、事務(wù)、存儲(chǔ)過(guò)程

寫(xiě)在前面

本文主要側(cè)重于索引、事務(wù)、優(yōu)化等方面的面試問(wèn)題。
原文鏈接:https://mp.weixin.qq.com/s/qmJ2kkK1gHPu9NwQYu4Sag

索引

1.什么是索引?
??索引是一種數(shù)據(jù)結(jié)構(gòu)、可以幫助我們快速的進(jìn)行數(shù)據(jù)查找。

2.索引是什么樣的數(shù)據(jù)結(jié)構(gòu)?
??索引根據(jù)數(shù)據(jù)引擎的不同主要可分為Hash索引、B+樹(shù)索引。
??常用的InnoDB引擎采用B+樹(shù)索引

3.Hash索引和B+樹(shù)索引分別存儲(chǔ)了什么
??Hash索引:存儲(chǔ)Hash值
??B+樹(shù)索引:非葉子節(jié)點(diǎn)存儲(chǔ)其子樹(shù)的最大(或最小)關(guān)鍵字,可以看成索引;葉子節(jié)點(diǎn)存儲(chǔ)全部關(guān)鍵字以及指向相應(yīng)記錄的指針,而且葉子節(jié)點(diǎn)的關(guān)鍵字按大小順序排序,相鄰葉子節(jié)點(diǎn)用指針鏈接

4.Hash索引和B+樹(shù)索引區(qū)別或者說(shuō)優(yōu)劣?
??Hash索引:底層實(shí)現(xiàn)為Hash表,進(jìn)行查詢時(shí),調(diào)用hash函數(shù)獲取到相應(yīng)的鍵值,之后進(jìn)行回表查詢獲得實(shí)際數(shù)據(jù)。
??B+樹(shù)索引:底層實(shí)現(xiàn)為多路平衡查找樹(shù),每次查找都是從根節(jié)點(diǎn)出發(fā),查找到葉子節(jié)點(diǎn)方可以獲得查找鍵值,然后根據(jù)查詢判斷是否需要回表查詢數(shù)據(jù)。
??優(yōu)缺點(diǎn):
???? ★ Hash索引進(jìn)行等值查詢更快,卻無(wú)法進(jìn)行范圍查詢。因?yàn)镠ash索引中經(jīng)過(guò)Hash函數(shù)建立索引之后,索引順序于原順序無(wú)法保持一致。
????★ B+樹(shù)索引天然支持范圍查詢。
????★ Hash索引不支持使用索引進(jìn)行排序,原理同上
????★ hash索引任何時(shí)候都避免不了回表查詢,而B(niǎo)+樹(shù)在符合某些條件(聚簇索引、覆蓋索引)的時(shí)候可以只通過(guò)索引完成查詢。
????★ Hash索引雖然在等值查詢上較快,但是不穩(wěn)定,性能不可預(yù)測(cè),當(dāng)某個(gè)鍵值存在大量重復(fù)的時(shí)候,發(fā)生hash碰撞,此時(shí)效率可能極差.而B(niǎo)+樹(shù)的查詢效率比較穩(wěn)定,對(duì)于所有的查詢都是從根節(jié)點(diǎn)到葉子節(jié)點(diǎn),且樹(shù)的高度較低.

5.什么是聚簇索引?
??聚簇索引確定表中數(shù)據(jù)的物理順序,InnoDB中只有主鍵引擎是聚簇索引,如果沒(méi)有主鍵,則挑選一個(gè)唯一鍵建立聚簇索引,如果沒(méi)有唯一鍵,則隱式的生成一個(gè)鍵來(lái)建立聚簇索引。當(dāng)查詢使用聚簇索引時(shí),在對(duì)應(yīng)的葉子節(jié)點(diǎn),可以獲取到整行數(shù)據(jù),因此不用再次進(jìn)行回表查詢。

6.非聚簇索引一定會(huì)回表查詢么?
??不一定,這涉及到查詢語(yǔ)句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再進(jìn)行回表查詢。

7. 建立索引的時(shí)候,需要考慮那些因素?
??字段的使用頻率,經(jīng)常作為i套件進(jìn)行查詢的字段比較適合,如果是聯(lián)合索引,還要考慮聯(lián)合索引中的順序。
??過(guò)多的索引會(huì)對(duì)表造成太大的壓力

8.聯(lián)合索引是什么?為什么需要注意聯(lián)合索引中順序?
??使用多個(gè)字段同時(shí)建立一個(gè)索引,叫做聯(lián)合索引。在聯(lián)合索引中如果想要命中索引,需要按照建立索引時(shí)的字段順序來(lái)挨個(gè)使用,否則無(wú)法命中索引

9.如何查看索引是否被用到?或者說(shuō)如何知道這條語(yǔ)句運(yùn)行很慢的原因
??expain

10.什么情況下會(huì)發(fā)生創(chuàng)建了索引卻未被使用,如何避免全表查詢?
?? ★ 最佳左前綴法則,是指聯(lián)合索引的查詢需要從索引的最左前列開(kāi)始并且不跳過(guò)索引中的列。(不必時(shí)全部索引參數(shù),但是中間不能跳過(guò),必須按照索引順序挨個(gè)使用)
?? ★ 不在索引列上做任何操作(計(jì)算、函數(shù)、(自動(dòng)or手動(dòng))類型轉(zhuǎn)換),會(huì)導(dǎo)致索引失效而轉(zhuǎn)向全表掃描。
?? ★ 存儲(chǔ)引擎不能使用索引范圍條件右邊的列。即在范圍條件(rang > <等)右邊的條件是自動(dòng)失去索引的。如 pos的索引不起作用。

EXPLAIN select * from staffs where name='July' AND age>25 and pos='dev';

?? ★ 盡量使用覆蓋索引(只訪問(wèn)索引的查詢(索引列和查詢列一致)),減少select *
?? ★ 使用不等號(hào)(!= 或者<>)、is null、is not null時(shí)無(wú)法使用索引
?? ★ like以通配符開(kāi)頭('%abc')索引失效
?? ★ 字符串不加單引號(hào)索引失效(底層會(huì)進(jìn)行隱式轉(zhuǎn)換)
?? ★ or 會(huì)導(dǎo)致索引失效

事務(wù)

Mysql中僅有Innodb數(shù)據(jù)庫(kù)引擎支持事務(wù)。事務(wù)主要是用于處理操作量大、復(fù)雜度高的數(shù)據(jù)
事務(wù)可用來(lái)維護(hù)數(shù)據(jù)庫(kù)的完整性,保證批量SQL要么全部執(zhí)行,要么全部不執(zhí)行。

四大特征(ACID)
??A(原子性):要么全部成功,要么全部失敗,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)執(zhí)行發(fā)生錯(cuò)誤會(huì)執(zhí)行回滾。
??C(一致性):
??I(隔離性):允許多個(gè)并發(fā)事務(wù)同時(shí)進(jìn)行讀寫(xiě),隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)的隔離性可分為四種:讀未提交、讀提交、可重復(fù)度、串行化
??D(持久性):事務(wù)處理結(jié)束后,對(duì)數(shù)據(jù)的修改是永久的,即便系統(tǒng)故障也不會(huì)丟失。

基本操作
??★ BEGIN/START TRANSACTION:顯式的開(kāi)啟一個(gè)事務(wù);
??★ COMMIT:提交事務(wù),并使已對(duì)數(shù)據(jù)庫(kù)進(jìn)行的所有修改成為永久性的;
??★ ROLLBACK:回滾,并撤銷正在進(jìn)行的所有未提交的修改;
??★ SAVEPOINT identifier:允許在事務(wù)中創(chuàng)建一個(gè)保存點(diǎn),一個(gè)事務(wù)中可以有多個(gè)SAVEOINT;
??★ RELEASE SAVEPOINT identifier:刪除一個(gè)事務(wù)的保存點(diǎn),當(dāng)沒(méi)有指定保存點(diǎn)時(shí),執(zhí)行該語(yǔ)句會(huì)拋出一個(gè)異常;
??★ ROLLBACK TO identifier:把事務(wù)回滾到標(biāo)記點(diǎn);
??★ SET TRANSACTION:用來(lái)設(shè)置事務(wù)的隔離級(jí)別;

注:事務(wù)在commit之后,無(wú)法再回滾。

事務(wù)的隔離特性
??★讀未提交(Read uncommitted):該級(jí)別僅存于理論中,無(wú)人使用
??★讀提交(Read committed):Oracle默認(rèn)隔離級(jí)別
??★可重復(fù)讀(repeatable read):MySql默認(rèn)隔離級(jí)別
??★串行化(Serializable):很少使用,事務(wù)操作需要排隊(duì),吞吐量太低,用戶體驗(yàn)差。串行而不是并發(fā)。

臟讀 不可重復(fù)讀 幻讀
讀未提交
讀提交 ×
可重復(fù)讀 × ×
串行化 × × ×

臟讀:指一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù),并且對(duì)數(shù)據(jù)進(jìn)行了修改,而這種修改還沒(méi)有提交到數(shù)據(jù)庫(kù)中,這時(shí),另一個(gè)事務(wù)也訪問(wèn)這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)。
不可重復(fù)讀:在事務(wù)執(zhí)行過(guò)程中讀取了其他事務(wù)更改的數(shù)據(jù),針對(duì)update操作。
??解決:使用行級(jí)鎖,事務(wù)在多次讀取操作完成后才釋放該鎖,才能允許其他事務(wù)更改數(shù)據(jù)。
幻讀:在事務(wù)執(zhí)行過(guò)程中讀取了其他事務(wù)新增的數(shù)據(jù),針對(duì)的是insert和delete操作。
??解決:使用表鎖,鎖定整張表,事務(wù)多次讀取數(shù)據(jù)完成后釋放該鎖,這個(gè)時(shí)候才允許其他事務(wù)新增數(shù)據(jù)。
注:幻讀和不可重復(fù)讀都是指的一個(gè)事務(wù)范圍內(nèi)的操作受到其他事務(wù)的影響了。只不過(guò)幻讀的重點(diǎn)在插入和刪除,不可重復(fù)讀的重點(diǎn)在修改。
事務(wù)實(shí)現(xiàn)原理
日志文件、鎖技術(shù)、MVCC(多版本并發(fā)控制)
參考博文:http://www.itdecent.cn/p/081a3e208e32

事務(wù)執(zhí)行過(guò)程斷電會(huì)如何?
??客戶端斷電:已提交服務(wù)器正常執(zhí)行,未提交則回滾
??服務(wù)器斷電:未提交回滾。已提交的事務(wù)會(huì)現(xiàn)在日志里面存放,通電后,已提交但未寫(xiě)入硬盤(pán)的會(huì)繼續(xù)寫(xiě)入,未提交的會(huì)在日志中回滾。
??服務(wù)器斷電后鎖全部取消(鎖存儲(chǔ)在內(nèi)存中)
參考博文:https://q.cnblogs.com/q/65483/

MYSQL 事務(wù)處理的兩種主要方法
??1.BEGIN、ROLLBACK、COMMIT實(shí)現(xiàn)
????★ BEGIN 開(kāi)啟事務(wù)
????★ ROLLBACK 事務(wù)回滾
????★ COMMIT 事務(wù)確認(rèn)
??2.直接用SET來(lái)改變MySQL的自動(dòng)提交模式
????★ SET AUTOCOMMIT=0 禁止自動(dòng)提交
????★ SET AUTOCOMMIT=1 開(kāi)啟自動(dòng)提交
案例

begin;   // 開(kāi)啟事務(wù)
insert into XXXXX
update XXXX
commit;  // 提交

存儲(chǔ)過(guò)程

定義:存儲(chǔ)過(guò)程是一種在數(shù)據(jù)庫(kù)中存儲(chǔ)復(fù)雜過(guò)程,以便外部程序調(diào)用的一種數(shù)據(jù)庫(kù)對(duì)象。存儲(chǔ)過(guò)程是為了完成特定功能的SQL語(yǔ)句集,經(jīng)編譯創(chuàng)建并保存在數(shù)據(jù)庫(kù)中。
存儲(chǔ)過(guò)程思想上很簡(jiǎn)單,就是數(shù)據(jù)庫(kù)SQL語(yǔ)言層面的代碼封裝與重用。
優(yōu)點(diǎn):
??★ 可封裝并隱藏復(fù)雜的邏輯。
??★ 不需要反復(fù)建立一系列的處理步驟,因而保證了數(shù)據(jù)的一致性。
??★ 簡(jiǎn)化了對(duì)變動(dòng)的管理,這一點(diǎn)的延伸就是安全性。
??★ 可存儲(chǔ)過(guò)程通常以編譯過(guò)的形式存儲(chǔ),提高了性能。
缺點(diǎn)
??★ 可移植性差,往往定制化與特定的數(shù)據(jù)庫(kù)上,切換數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程可能需要重寫(xiě)。
??★ 存儲(chǔ)過(guò)程性能調(diào)教與撰寫(xiě),受限于各種數(shù)據(jù)庫(kù)系統(tǒng)。
JAVA開(kāi)發(fā)手冊(cè):
??強(qiáng)制禁止使用存儲(chǔ)過(guò)程,存儲(chǔ)過(guò)程難以調(diào)試和擴(kuò)展,更沒(méi)有移植性。
創(chuàng)建與調(diào)用
參考博文:https://www.cnblogs.com/chenliyang/p/6553068.html

CREATE PROCEDURE `name` (IN | OUT | INOUT params_name type , ...)  //定義存儲(chǔ)過(guò)程

DECLARE kind int unsigned default 0;   //定義變量
DECLARE l_numeric number(8,2) DEFAULT 9.95;  
DECLARE l_date date DEFAULT '1999-12-31';  

BEGIN   // 存儲(chǔ)過(guò)程開(kāi)始

IF kind=1 THEN // if 條件語(yǔ)句
    SELECT AVG(item_price) INTO Pavg FROM order_items;//  INTO 將查詢值賦給輸出變量
  ELSEIF kind=2 THEN
    SELECT MAX(item_price) INTO Pmax FROM order_items;
  ELSE
    SELECT MIN(item_price) INTO Pmin FROM order_items; 
END IF;  // IF結(jié)束

CASE kind  // case 選擇語(yǔ)句
   WHEN 0 THEN
      update order_items set item_price=0;
   WHEN 1 THEN
      update order_items set item_price=1;
   ELSE
      update order_items set item_price=2;
END CASE; // case 結(jié)束

WHILE kind < 6  // while循環(huán)  先檢查結(jié)果后執(zhí)行操作
  DO  
      INSERT INTO order_items (item_price) VALUES (kind);
      SET kind = kind+1;
END WHILE; // while循環(huán)結(jié)束

REPEAT    //repeat 循環(huán)  先執(zhí)行操作后檢查結(jié)果
        INSERT INTO order_items (item_price) VALUES (kind);
        SET kind = kind + 1;
   UNTIL kind >=5;
END REPEAT;  repeat循環(huán)結(jié)束

LOOP_LABLE: loop  // loop循環(huán)開(kāi)始
       INSERT INTO order_items (item_price) VALUES (kind);
       SET kind = kind + 1;
       if kind >= 5 then
          leave LOOP_LABLE;
       end if
END LOOP;  

END;    //存儲(chǔ)過(guò)程結(jié)束

參數(shù)說(shuō)明:
??★ name:存儲(chǔ)過(guò)程名
??★ params_name:自定義參數(shù)名
??★ type:參數(shù)類型
??★ IN:輸入?yún)?shù),表示調(diào)用者想過(guò)程傳入值(傳入值可以是字面量或變量)
??★ OUT:輸出參數(shù),表示過(guò)程向調(diào)用者傳出值(傳出值只能是變量)
??★ INOUT:輸入輸出參數(shù),既表示調(diào)用者向過(guò)程傳入值,又表示過(guò)程向調(diào)用者傳出值(值只能是變量)
定義變量
??存儲(chǔ)過(guò)程可定義變量,但變量聲明一定要放在存儲(chǔ)過(guò)程的開(kāi)始
**
調(diào)用
??CALL name(@a,@b,@c)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 索引 數(shù)據(jù)庫(kù)中的查詢操作非常普遍,索引就是提升查找速度的一種手段 索引的類型 從數(shù)據(jù)結(jié)構(gòu)角度分 1.B+索引:傳統(tǒng)...
    一凡呀閱讀 3,221評(píng)論 0 8
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,983評(píng)論 0 9
  • 一、索引是做什么的? 很多時(shí)候,當(dāng)你的應(yīng)用程序進(jìn)行SQL查詢速度很慢時(shí),應(yīng)該想想是否可以建索引。 大多數(shù)MySQL...
    wuxiumu閱讀 473評(píng)論 0 1
  • --- layout: post title: "如果有人問(wèn)你關(guān)系型數(shù)據(jù)庫(kù)的原理,叫他看這篇文章(轉(zhuǎn))" date...
    藍(lán)墜星閱讀 919評(píng)論 0 3
  • MySql數(shù)據(jù)庫(kù)索引原理 寫(xiě)在前面:索引對(duì)查詢的速度有著至關(guān)重要的影響,理解索引也是進(jìn)行數(shù)據(jù)庫(kù)性能調(diào)優(yōu)的起點(diǎn)??紤]...
    琴匣自鳴閱讀 1,798評(píng)論 0 2

友情鏈接更多精彩內(nèi)容