索引
索引的介紹
索引是幫助MySQL高效獲取數據的數據結構,是一種特殊的文件,包含著對數據表里所有記錄的引用指針,因為索引本身也比較大,所以索引一般是存儲在磁盤上的,索引的種類有很多,不過如果沒有特殊說明,我們一般認為索引是一個B+樹的結構。
索引的作用
優勢:
- 可以提高列檢索的效率,降低搜索成本。
- 對提高數據庫的性能有很大的作用。
- 通過索引對數據進行,排序也可以大大提高排序效率
- 數據庫中的表、數據、索引之間的關系,類似于書架上的圖書、書籍內容和書籍目錄的關系。
劣勢:
- 會占用磁盤空間
- 有時可能會比較危險,在創建索引時需要對現有的數據,進行大規模的從新整理(調整存儲的數據結構),如果當前是一個空表,或者數據不多,創建索引一般沒有什么問題,如果這個表本來就很大,此時創建索引就需要對所有數據進行重新調整結構,重新存儲,就有可能把服務器給卡住,一般來說,創建索引都是在創建表時就規劃好的。
索引的使用
查看索引
show index from 表名;
舉例:
create table demo(
id int primary key,
age int,
name varchar(20));
show index from demo;
創建索引
create index 索引名字 on 表名(列名);
舉例:
create index index_id on demo(id);
show index from demo;
//這里的舉例只是為了講解
刪除索引
drop index 索引名 on 表名;
drop index index_id on demo;show index from demo;
//主鍵,unique,外鍵都是會自動生成索引的
索引內部的原理和邏輯
如果沒有特殊說明,我們一般認為索引是一個B+樹的結構。
二叉搜索樹
博主在之前的博客中有詳細講解過二叉搜索樹,如果有興趣可以去看看。
B樹
在將B+樹之前我們要先了解一些B樹,B樹又叫多路平衡查找樹,他并不是一棵二叉樹,而是一棵多叉樹,每個結點有M個子節點,M稱為B樹的階,
B樹的特點包括:
- 每個節點可以有多個子節點,這使得B樹能夠優化大塊數據的讀寫操作。
- B樹的所有葉子節點都在同一層,保持了樹的平衡。
- B樹中的關鍵字從小到大排列,每個結點上有M個key,劃分出M+1個區間
- 葉子節點不包含關鍵字,指向這些外部結點的指針為空,葉子結點的數目正好等于樹中所包含的關鍵字總個數加1。
每個結點可以看作是一個區間,從無窮小到無窮大,每一個關鍵字都會將這個區間劃分,每個小區間又可以向下延申出子結點,又或者說每個結點里所包含的關鍵字大小,都在其對應的父結點,的相應的小區間里
舉例:查找7
首先從根結點開始,7比10小,所以在10左邊的區間,然后繼續查找比較,7比3大,在3右邊的區間,繼續查找比較,在這個結點中可以查找到7,查找結束。
進行查詢的時候,就可以直接從根結點出發,判定當前要查找的數據在節點上的哪個區間,決定下一步往哪里走,進行添加/刪除元素可能會涉及到結點的拆分和結點的合并
//B樹可以有效的減少訪問硬盤的次數,從而大大提高檢索的性能
B+樹
- 為了進一步提高檢索的性能,在B樹的基礎上改造得到了B+樹,B+樹是B樹的改進,針對數據庫量身定做
- B+樹也是一個N叉搜索樹,一個結點上存在N個key,劃分成N個區域
- 每個節點上N個key中,最后一個就相當于當前子樹的最大值
- 父節點上的每個key都會以最大值的身份,在子節點的對應區間中存在(key可能會重復出現)
- 葉子節點這一層,包含整個樹的數據全集
- B+樹會以鏈表的形式,把葉子節點串起來(此時就方便我們進行遍歷,也方便按照范圍取出一個子集)
假如說要查詢id>26 and id<62的就可以根據head進行查找
B+樹的優點(相較于B樹以及哈希,紅黑樹)
- N叉搜索樹,樹的高度有限,降低了IO次數,增加了效率
- 范圍查找效率較高
- 所有查詢的最終結果都落到子節點,查詢次數較穩定
- 由于葉子結點是全集,會把行數據只存儲在葉子節點上,非葉子節點只是存儲一個用來排序的key(比如存個id)
事務
事務的介紹
我們先來舉一個例子,假如我們現在要去銀行把錢轉賬給另一個人,那么把這個操作簡化為MySQL語句的話,就是我的賬戶刪除一條數據,另一個人的賬戶插入一條數據,那么假如中間出現了錯誤,我的賬戶少了,另一個人的賬戶沒有變,這樣的場景顯然是不合理的。
事務就是將多條sql語句打包為一個整體,要么都執行,要么都不執行,事務把多個sql打包為一個整體來執行,稱之為“原子性”(意為不可再拆分)。
也就是說,在執行事務時如果其中有一條或者多條語句出現錯誤,那么所有執行的語句都會回滾(回到執行前的狀態),收到影響的數據也會回到事務開始之前的狀態,當所有語句都執行成功后事務也就順利進行了
?事務不僅僅有原子性,還有一些其他方面的特性
- 原子性:回滾的方式,保證這一系列操作都能執行正確,或者恢復如初
- 一致性:事務執行之前,和之后要保證數據的合理性,比如不能出現前文例子中的,一方賬戶的金額少了,一方賬戶金額不變
- 持久性:事務做出的修改都是在硬盤上持久保存的,重啟服務器,數據仍然存在,事務執行的修改任然是有效的
- 隔離性:一個事務的執行不能被其他事務干擾,數據庫在并發執行時事務之間是隔離的
事務的使用
隱式事務
沒有明確的開始和提交的標志,具有自動開始和提交事務的功能,在默認狀態下mysql就是自動提交事務
顯式事務
和隱式事務不同需要自己,手動開始事務和提交(commit)/回滾(rollback),在使用顯式事務時要先將自動提交事務關掉,方法就是將變量autocommit的值改為0
首先準備一個表
具體步驟如下
#第一步開始事務
start transaction;
#第二步編寫事務中的sql語句
update test2 set gpa = 3.8 where id = 6;
update test2 set gpa = 4.1 where id = 5;
#第四步提交事務
commit;
#rollback,回滾事務,將數據回到執行事務之前
并發事務時會遇到的問題
臟讀
一個事務A正在寫數據的過程中,另一個事務B讀取了同一個數據,接下來事務A又修改了數據,導致B之前讀的數據是一個無效的數據/過時的數據(也稱為臟數據)
解決臟讀的核心思路,就是對寫操作進行加鎖(規定在A寫的時候B不可以讀),之前A和B時并發執行的,在加鎖之后,并發程度和效率就降低了,但是隔離性和數據準確性提高了
不可重復讀
在并發執行事務的過程中,如果事務A在內部多次讀取同一個數據的時候,出現不同的情況,這種情況就是不可重復讀,即事務A在兩次相鄰的讀取操作之間,有一個事務B修改了數據并提交了事務。
剛剛寫加鎖時,我們只是規定在寫的時候不能讀,但是沒有規定在讀的時候不能寫,那么我們想要解決不可重復讀就要再進一步加鎖,也就是規定在讀的時候也不能寫。
這樣之后,并發程度和效率就又降低了,但是隔離性和數據準確性依然提高了
幻讀
一個事務A執行過程中,兩次讀取操作,數據內容雖然沒改變,但是結果集變了(比如又多出一個文件),雖然我們剛剛約定了,在讀的時候能寫,在寫的時候不能讀但是,當事務A再寫A文件的時候事務B不能讀A文件,但是事務B可以讀B文件
這時我們只好從根本上解決,將兩個事務完全分離,比如A執行完了之后才能執行B,這樣就完全沒有并發,效率自然是最低,但是隔離性和數據準確性都是最高
事務的隔離級別
一個事務和另一個事務的隔離程度稱作隔離級別,
- read uncommitted(讀未提交)? 沒有加鎖,并發程度最高,速度最快,隔離性最低,準確性最低
- read committed(讀已提交) 引入寫加鎖,只能讀寫完之后提交的版本,并發程度降低,速度降低,隔離性提高了,準確性提高了
- repeatable read(可重復讀)? 引入了寫加鎖和讀加鎖,寫的時候不能讀,讀的時候不能寫,并發程度又進一步降低了,速度降低,隔離性提高,準確性提高
- serializable(串行化)嚴格的按照串行的方式,一個一個的執行事務,并發事務最低(沒有并發),速度最低,隔離性最高,準確性最高
//四種隔離級別對應上面的三個問題,隔離級別越高,并發程度越低,準確性越高,速度越慢。
oracle默認的事務隔離級別是:read committed
mysql默認的事務隔離級別是:read committed
以上就是博主對mysql--索引事務的分享,如果有不懂的或者有其他見解的歡迎在下方評論或者私信博主,也希望多多支持博主之后和博客!!🥰🥰