MySQL基础总结(一)
MySQL基礎總結(一)
文章目錄
- MySQL基礎總結(一)
- 一、MySQL架構
- 1.MySQL架構圖
- 2.SQL語句在MySQL中的執(zhí)行流程
- 二、存儲引擎
- 1.查看存儲引擎
- 2.設置存儲引擎
- 3.存儲引擎對比
- 文件存儲結構對比
- MyISAM和Innodb的區(qū)別
- 一張表,里面有ID自增主鍵,當insert了17條記錄之后,刪除了第15,16,17條記錄,再把Mysql重啟,再insert一條記錄,這條記錄的ID是18還是15 ?
- 哪個存儲引擎執(zhí)行 select count(*) 更快,為什么?
- 三、數(shù)據(jù)類型
- 1.CHAR 和 VARCHAR 的區(qū)別?
- 2.列的字符串類型可以是什么?
- 3.BLOB和TEXT有什么區(qū)別?
- 四、索引
- 1.基本語法:
- 創(chuàng)建:
- 修改表結構(添加索引):
- 刪除:
- 查看:
- 使用ALERT命令
- 2.優(yōu)勢
- 3.劣勢
- 4.MySQL索引分類
- 數(shù)據(jù)結構角度
- 從物理存儲角度
- 從邏輯角度
- 5.MySQL索引結構
- 6.B+Tree索引
- B-Tree:
- B+Tree:
一、MySQL架構
和其它數(shù)據(jù)庫相比,MySQL有點與眾不同,它的架構可以在多種不同場景中應用并發(fā)揮良好作用。
主要體現(xiàn)在存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統(tǒng)任務以及數(shù)據(jù)的存儲提取相分離。這種架構可以根據(jù)業(yè)務的需求和實際需要選擇合適的存儲引擎。
1.MySQL架構圖
- 連接層:最上層是一些客戶端和連接服務。主要完成一些類似于連接處理、授權認證、及相關的安全方案。在該層上引入了線程池的概念,為通過認證安全接入的客戶端提供線程。同樣在該層上可以實現(xiàn)基于SSL的安全鏈接。服務器也會為安全接入的每個客戶端驗證它所具有的操作權限。
- 服務層:第二層服務層,主要完成大部分的核心服務功能, 包括查詢解析、分析、優(yōu)化、緩存、以及所有的內置函數(shù),所有跨存儲引擎的功能也都在這一層實現(xiàn),包括觸發(fā)器、存儲過程、視圖等
- 引擎層:第三層存儲引擎層,存儲引擎真正的負責了MySQL中數(shù)據(jù)的存儲和提取,服務器通過API與存儲引擎進行通信。不同的存儲引擎具有的功能不同,這樣我們可以根據(jù)自己的實際需要進行選取
- 存儲層:第四層為數(shù)據(jù)存儲層,主要是將數(shù)據(jù)存儲在運行于該設備的文件系統(tǒng)之上,并完成與存儲引擎的交互
2.SQL語句在MySQL中的執(zhí)行流程
客戶端請求 —> 連接器(驗證用戶身份,給予權限) —> 查詢緩存(存在緩存則直接返回,不存在則執(zhí)行后續(xù)操作) —> 分析器(對SQL進行詞法分析和語法分析操作) —> 優(yōu)化器(主要對執(zhí)行的sql優(yōu)化選擇最優(yōu)的執(zhí)行方案方法) —> 執(zhí)行器(執(zhí)行時會先看用戶是否有執(zhí)行權限,有才去使用這個引擎提供的接口) —> 去引擎層獲取數(shù)據(jù)返回(如果開啟查詢緩存則會緩存查詢結果)
二、存儲引擎
存儲引擎是MySQL的組件,用于處理不同表類型的SQL操作。不同的存儲引擎提供不同的存儲機制、索引技巧、鎖定水平等功能,使用不同的存儲引擎,還可以獲得特定的功能。
使用哪一種引擎可以靈活選擇,一個數(shù)據(jù)庫中多個表可以使用不同引擎以滿足各種性能和實際需求,使用合適的存儲引擎,將會提高整個數(shù)據(jù)庫的性能 。
MySQL服務器使用可插拔的存儲引擎體系結構,可以從運行中的 MySQL 服務器加載或卸載存儲引擎 。
1.查看存儲引擎
-- 查看支持的存儲引擎 SHOW ENGINES-- 查看默認存儲引擎 SHOW VARIABLES LIKE 'storage_engine'--查看具體某一個表所使用的存儲引擎,這個默認存儲引擎被修改了! show create table tablename--準確查看某個數(shù)據(jù)庫中的某一表所使用的存儲引擎 show table status like 'tablename' show table status from database where name="tablename"2.設置存儲引擎
-- 建表時指定存儲引擎。默認的就是INNODB,不需要設置 CREATE TABLE t1 (i INT) ENGINE = INNODB; CREATE TABLE t2 (i INT) ENGINE = CSV; CREATE TABLE t3 (i INT) ENGINE = MEMORY;-- 修改存儲引擎 ALTER TABLE t ENGINE = InnoDB;-- 修改默認存儲引擎,也可以在配置文件my.cnf中修改默認引擎 SET default_storage_engine=NDBCLUSTER;默認情況下,每當 CREATE TABLE 或 ALTER TABLE 不能使用默認存儲引擎時,都會生成一個警告。
為了防止在所需的引擎不可用時出現(xiàn)令人困惑的意外行為,可以啟用 NO_ENGINE_SUBSTITUTION SQL 模式。如果所需的引擎不可用,則此設置將產(chǎn)生錯誤而不是警告,并且不會創(chuàng)建或更改表
3.存儲引擎對比
常見的存儲引擎就 InnoDB、MyISAM、Memory、NDB。
InnoDB 現(xiàn)在是 MySQL 默認的存儲引擎,支持事務、行級鎖定和外鍵
文件存儲結構對比
- 在 MySQL中建立任何一張數(shù)據(jù)表,在其數(shù)據(jù)目錄對應的數(shù)據(jù)庫目錄下都有對應表的 .frm 文件,.frm 文件是用來保存每個數(shù)據(jù)表的元數(shù)據(jù)(meta)信息,包括表結構的定義等,與數(shù)據(jù)庫存儲引擎無關,也就是任何存儲引擎的數(shù)據(jù)表都必須有.frm文件,命名方式為 數(shù)據(jù)表名.frm,如user.frm。
-
MyISAM 物理文件結構為:
-
.frm文件:與表相關的元數(shù)據(jù)信息都存放在frm文件,包括表結構的定義信息等
-
.MYD (MYData) 文件:MyISAM 存儲引擎專用,用于存儲MyISAM 表的數(shù)據(jù)
-
.MYI (MYIndex)文件:MyISAM 存儲引擎專用,用于存儲MyISAM 表的索引相關信息
-
InnoDB 物理文件結構為:
-
.frm 文件:與表相關的元數(shù)據(jù)信息都存放在frm文件,包括表結構的定義信息等
-
.ibd 文件或 .ibdata 文件:這兩種文件都是存放 InnoDB 數(shù)據(jù)的文件,之所以有兩種文件形式存放 InnoDB 的數(shù)據(jù),是因為 InnoDB 的數(shù)據(jù)存儲方式能夠通過配置來決定是使用共享表空間存放存儲數(shù)據(jù),還是用獨享表空間存放存儲數(shù)據(jù)。
-
獨享表空間存儲方式使用.ibd文件,并且每個表一個.ibd文件; 共享表空間存儲方式使用.ibdata文件,所有表共同使用一個.ibdata文件(或多個,可自己配置)
MyISAM和Innodb的區(qū)別
- InnoDB 支持事務,MyISAM 不支持事務。這是 MySQL 將默認存儲引擎從 MyISAM 變成 InnoDB 的重要原因之一;
- InnoDB 支持外鍵,而 MyISAM 不支持。對一個包含外鍵的 InnoDB 表轉為 MYISAM 會失敗;
- InnoDB 是聚簇索引,MyISAM 是非聚簇索引。聚簇索引的文件數(shù)據(jù)存放在主鍵索引的葉子節(jié)點上,因此 InnoDB 必須要有主鍵,通過主鍵索引效率很高。但是輔助索引需要兩次查詢,先查詢到主鍵,然后再通過主鍵查詢到數(shù)據(jù)。因此,主鍵不應該過大,因為主鍵太大,其他索引也都會很大。而 MyISAM 是非聚集索引,數(shù)據(jù)文件和索引是分離的,無論是主鍵索引還是輔助索引保存的都是數(shù)據(jù)文件的指針。主鍵索引和輔助索引是獨立的。
- InnoDB 不保存表的具體行數(shù),執(zhí)行select count(*) from table 時需要全表掃描。而 MyISAM 用一個變量保存了整個表的行數(shù),執(zhí)行上述語句時只需要讀出該變量即可,速度很快;
- InnoDB 最小的鎖粒度是行鎖,MyISAM 最小的鎖粒度是表鎖。一個更新語句會鎖住整張表,導致其他查詢和更新都會被阻塞,因此并發(fā)訪問受限。這也是 MySQL 將默認存儲引擎從 MyISAM 變成 InnoDB 的重要原因之一;
一張表,里面有ID自增主鍵,當insert了17條記錄之后,刪除了第15,16,17條記錄,再把Mysql重啟,再insert一條記錄,這條記錄的ID是18還是15 ?
- 如果表的類型是MyISAM,那么是18。因為MyISAM表會把自增主鍵的最大ID 記錄到數(shù)據(jù)文件中,重啟MySQL自增主鍵的最大ID也不會丟失;
- 如果表的類型是InnoDB,那么是15。因為InnoDB 表只是把自增主鍵的最大ID記錄到內存中,所以重啟數(shù)據(jù)庫或對表進行OPTION操作,都會導致最大ID丟失。
哪個存儲引擎執(zhí)行 select count(*) 更快,為什么?
MyISAM更快,因為MyISAM內部維護了一個計數(shù)器,可以直接調取。
- 在 MyISAM 存儲引擎中,把表的總行數(shù)存儲在磁盤上,當執(zhí)行 select count(*) from t 時,直接返回總數(shù)據(jù)。
- 在 InnoDB 存儲引擎中,跟 MyISAM 不一樣,沒有將總行數(shù)存儲在磁盤上,當執(zhí)行 select count(*) from t 時,會先把數(shù)據(jù)讀出來,一行一行的累加,最后返回總數(shù)量。
- InnoDB 中 count(*) 語句是在執(zhí)行的時候,全表掃描統(tǒng)計總數(shù)量,所以當數(shù)據(jù)越來越大時,語句就越來越耗時了
為什么 InnoDB 引擎不像 MyISAM 引擎一樣,將總行數(shù)存儲到磁盤上?
- 這跟 InnoDB 的事務特性有關,由于多版本并發(fā)控制(MVCC)的原因,InnoDB 表“應該返回多少行”也是不確定的。
三、數(shù)據(jù)類型
主要包括以下五大類:
- 整數(shù)類型:BIT、BOOL、TINY INT、SMALL INT、MEDIUM INT、 INT、 BIG INT
- 浮點數(shù)類型:FLOAT、DOUBLE、DECIMAL
- 字符串類型:CHAR、VARCHAR、TINY TEXT、TEXT、MEDIUM TEXT、LONGTEXT、TINY BLOB、BLOB、MEDIUM BLOB、LONG BLOB
- 日期類型:Date、DateTime、TimeStamp、Time、Year
- 其他數(shù)據(jù)類型:BINARY、VARBINARY、ENUM、SET、Geometry、Point、MultiPoint、LineString、MultiLineString、Polygon、GeometryCollection等
1.CHAR 和 VARCHAR 的區(qū)別?
- char是固定長度,varchar長度可變:
- char(n) 和 varchar(n) 中括號中 n 代表字符的個數(shù),并不代表字節(jié)個數(shù),比如 CHAR(30) 就可以存儲 30 個字符。
- 存儲時,前者不管實際存儲數(shù)據(jù)的長度,直接按 char 規(guī)定的長度分配存儲空間;而后者會根據(jù)實際存儲的數(shù)據(jù)分配最終的存儲空間
- 相同點:
- char(n),varchar(n)中的n都代表字符的個數(shù)
- 超過char,varchar最大長度n的限制后,字符串會被截斷。
- 不同點:
- char不論實際存儲的字符數(shù)都會占用n個字符的空間,而varchar只會占用實際字符應該占用的字節(jié)空間加1(實際長度length,0<=length<255)或加2(length>255)
- 因為varchar保存數(shù)據(jù)時除了要保存字符串之外還會加一個字節(jié)來記錄長度(如果列聲明長度大于255則使用兩個字節(jié)來保存長度)。
- 能存儲的最大空間限制不一樣:char的存儲上限為255字節(jié)。
- char在存儲時會截斷尾部的空格,而varchar不會。
- char是適合存儲很短的、一般固定長度的字符串。例如,char非常適合存儲密碼的MD5值,因為這是一個定長的值。對于非常短的列,char比varchar在存儲空間上也更有效率。
2.列的字符串類型可以是什么?
字符串類型是:SET、BLOB、ENUM、CHAR、CHAR、TEXT、VARCHAR
3.BLOB和TEXT有什么區(qū)別?
- BLOB是一個二進制對象,可以容納可變數(shù)量的數(shù)據(jù)
- 有四種類型的BLOB:TINYBLOB、BLOB、MEDIUMBLO和 LONGBLOB
- TEXT是一個不區(qū)分大小寫的BLOB
- 四種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。
BLOB 保存二進制數(shù)據(jù),TEXT 保存字符數(shù)據(jù)
四、索引
MYSQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結構,所以說索引的本質是:數(shù)據(jù)結構
- 索引的目的在于提高查詢效率,可以類比字典、 火車站的車次表、圖書的目錄等 。
- 可以簡單的理解為“排好序的快速查找數(shù)據(jù)結構”,數(shù)據(jù)本身之外,數(shù)據(jù)庫還維護者一個滿足特定查找算法的數(shù)據(jù)結構,這些數(shù)據(jù)結構以某種方式引用(指向)數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結構上實現(xiàn)高級查找算法。
- 這種數(shù)據(jù)結構,就是索引。
下圖是一種可能的索引方式示例:
- 左邊的數(shù)據(jù)表,一共有兩列七條記錄,最左邊的是數(shù)據(jù)記錄的物理地址。
- 為了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節(jié)點分別包含索引鍵值,和一個指向對應數(shù)據(jù)記錄物理地址的指針,這樣就可以運用二叉查找在一定的復雜度內獲取到對應的數(shù)據(jù),從而快速檢索出符合條件的記錄。
- 索引本身也很大,不可能全部存儲在內存中,一般以索引文件的形式存儲在磁盤上
- 平常說的索引,沒有特別指明的話,就是B+樹結構組織的索引。
- 其中聚集索引,次要索引,覆蓋索引,符合索引,前綴索引,唯一索引默認都是使用B+樹索引,統(tǒng)稱索引。此外還有哈希索引等。
1.基本語法:
創(chuàng)建:
- 創(chuàng)建索引:
如果是CHAR,VARCHAR類型,length可以小于字段實際長度;如果是BLOB和TEXT類型,必須指定 length。
修改表結構(添加索引):
ALTER table tableName ADD [UNIQUE] INDEX indexName(columnName)刪除:
DROP INDEX [indexName] ON mytable;查看:
SHOW INDEX FROM table_name\G --可以通過添加 \G 來格式化輸出信息。使用ALERT命令
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list) 該語句添加一個主鍵,這意味著索引值必須是唯一的,且不能為NULL。ALTER TABLE tbl_name ADD UNIQUE index_name (column_list) 這條語句創(chuàng)建索引的值必須是唯一的(除了NULL外,NULL可能會出現(xiàn)多次)。ALTER TABLE tbl_name ADD INDEX index_name (column_list) 添加普通索引,索引值可出現(xiàn)多次。ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list) 該語句指定了索引為 FULLTEXT ,用于全文索引。2.優(yōu)勢
- 提高數(shù)據(jù)檢索效率,降低數(shù)據(jù)庫IO成本
- 降低數(shù)據(jù)排序的成本,降低CPU的消耗
3.劣勢
- 索引也是一張表,保存了主鍵和索引字段,并指向實體表的記錄,所以也需要占用內存
- 雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件每次更新添加了索引列的字段, 都會調整因為更新所帶來的鍵值變化后的索引信息
4.MySQL索引分類
數(shù)據(jù)結構角度
- B+樹索引
- Hash索引
- Full-Text全文索引
- R-Tree索引
從物理存儲角度
- 聚集索引(clustered index)
- 非聚集索引(non-clustered index),也叫輔助索引(secondary index)
聚集索引和非聚集索引都是B+樹結構
從邏輯角度
- 主鍵索引:主鍵索引是一種特殊的唯一索引,不允許有空值
- 普通索引或者單列索引:每個索引只包含單個列,一個表可以有多個單列索引
- 多列索引(復合索引、聯(lián)合索引):復合索引指多個字段上創(chuàng)建的索引,只有在查詢條件中使用了創(chuàng)建索引時的第一個字段,索引才會被使用。使用復合索引時遵循最左前綴集合
- 唯一索引或者非唯一索引
- 空間索引:空間索引是對空間數(shù)據(jù)類型的字段建立的索引,MYSQL中的空間數(shù)據(jù)類型有4種,分別是GEOMETRY、POINT、LINESTRING、POLYGON。
MYSQL使用SPATIAL關鍵字進行擴展,使得能夠用于創(chuàng)建正規(guī)索引類型的語法創(chuàng)建空間索引。創(chuàng)建空間索引的列,必須將其聲明為NOT NULL,空間索引只能在存儲引擎為MYISAM的表中創(chuàng)建
5.MySQL索引結構
首先要明白索引(index)是在存儲引擎(storage engine)層面實現(xiàn)的,而不是server層面。不是所有的存儲引擎都支持所有的索引類型。即使多個存儲引擎支持某一索引類型,它們的實現(xiàn)和行為也可能有所差別。
6.B+Tree索引
MyISAM 和 InnoDB 存儲引擎,都使用 B+Tree的數(shù)據(jù)結構,它相對與 B-Tree結構,所有的數(shù)據(jù)都存放在葉子節(jié)點上,且把葉子節(jié)點通過指針連接到一起,形成了一條數(shù)據(jù)鏈表,以加快相鄰數(shù)據(jù)的檢索效率。
先了解下 B-Tree 和 B+Tree 的區(qū)別:
B-Tree:
- B-Tree是為磁盤等外存儲設備設計的一種平衡查找樹
- 系統(tǒng)從磁盤讀取數(shù)據(jù)到內存時是以磁盤塊(block)為基本單位的,位于同一個磁盤塊中的數(shù)據(jù)會被一次性讀取出來,而不是需要什么取什么。
- InnoDB 存儲引擎中有頁(Page)的概念,頁是其磁盤管理的最小單位
- InnoDB 存儲引擎中默認每個頁的大小為16KB,可通過參數(shù) innodb_page_size 將頁的大小設置為 4K、8K、16K
- 在 MySQL 中可通過如下命令查看頁的大小:
- 而系統(tǒng)一個磁盤塊的存儲空間往往沒有這么大,因此 InnoDB 每次申請磁盤空間時都會是若干地址連續(xù)磁盤塊來達到頁的大小 16KB。
- InnoDB 在把磁盤數(shù)據(jù)讀入到磁盤時會以頁為基本單位,在查詢數(shù)據(jù)時如果一個頁中的每條數(shù)據(jù)都能有助于定位數(shù)據(jù)記錄的位置,這將會減少磁盤I/O次數(shù),提高查詢效率。
- B-Tree 結構的數(shù)據(jù)可以讓系統(tǒng)高效的找到數(shù)據(jù)所在的磁盤塊。
- 為了描述 B-Tree,首先定義一條記錄為一個二元組[key, data] ,key為記錄的鍵值,對應表中的主鍵值,data 為一行記錄中除主鍵外的數(shù)據(jù)。對于不同的記錄,key值互不相同。
- 一棵m階的B-Tree有如下特性:
- 每個節(jié)點最多有m個孩子
- 除了根節(jié)點和葉子節(jié)點外,其它每個節(jié)點至少有Ceil(m/2)個孩子。
- 若根節(jié)點不是葉子節(jié)點,則至少有2個孩子
- 所有葉子節(jié)點都在同一層,且不包含其它關鍵字信息
- 每個非終端節(jié)點包含n個關鍵字信息(P0,P1,…Pn, k1,…kn)
- 關鍵字的個數(shù)n滿足:ceil(m/2)-1 <= n <= m-1
- ceil代表向上取整
- ki(i=1,…n)為關鍵字,且關鍵字升序排序
- Pi(i=1,…n)為指向子樹根節(jié)點的指針。
- P(i-1)指向的子樹的所有節(jié)點關鍵字均小于ki,但都大于k(i-1)
- B-Tree 中的每個節(jié)點根據(jù)實際情況可以包含大量的關鍵字信息和分支,如下圖所示為一個 3 階的 B-Tree:
- 每個節(jié)點占用一個盤塊的磁盤空間,一個節(jié)點上有兩個升序排序的關鍵字和三個指向子樹根節(jié)點的指針,指針存儲的是子節(jié)點所在磁盤塊的地址。
- 兩個關鍵詞劃分成的三個范圍域對應三個指針指向的子樹的數(shù)據(jù)的范圍域。
- 以根節(jié)點為例,關鍵字為17和35,P1指針指向的子樹的數(shù)據(jù)范圍為小于17,P2指針指向的子樹的數(shù)據(jù)范圍為17~35,P3指針指向的子樹的數(shù)據(jù)范圍為大于35。
- 模擬查找關鍵字29的過程: 根據(jù)根節(jié)點找到磁盤塊1,讀入內存。【磁盤I/O操作第1次】
- 比較關鍵字29在區(qū)間(17,35),找到磁盤塊1的指針P2。
- 根據(jù)P2指針找到磁盤塊3,讀入內存。【磁盤I/O操作第2次】
- 比較關鍵字29在區(qū)間(26,30),找到磁盤塊3的指針P2。
- 根據(jù)P2指針找到磁盤塊8,讀入內存。【磁盤I/O操作第3次】
- 在磁盤塊8中的關鍵字列表中找到關鍵字29。
- 分析上面過程,發(fā)現(xiàn)需要3次磁盤I/O操作,和3次內存查找操作。
- 由于內存中的關鍵字是一個有序表結構,可以利用二分法查找提高效率。
- 而3次磁盤I/O操作是影響整個B-Tree查找效率的決定因素。
- B-Tree相對于AVLTree縮減了節(jié)點個數(shù),使每次磁盤I/O取到內存的數(shù)據(jù)都發(fā)揮了作用,從而提高了查詢效率。
B+Tree:
- B+Tree 是在 B-Tree 基礎上的一種優(yōu)化,使其更適合實現(xiàn)外存儲索引結構,InnoDB 存儲引擎就是用 B+Tree 實現(xiàn)其索引結構。
- 從B-Tree結構圖中可以看到每個節(jié)點中不僅包含數(shù)據(jù)的key值,還有data值。
- 而每一個頁的存儲空間是有限的,如果data數(shù)據(jù)較大時將會導致每個節(jié)點(即一個頁)能存儲的key的數(shù)量很小,當存儲的數(shù)據(jù)量很大時同樣會導致B-Tree的深度較大,增大查詢時的磁盤I/O次數(shù),進而影響查詢效率。
- 在 B+Tree中,所有數(shù)據(jù)記錄節(jié)點都是按照鍵值大小順序存放在同一層的葉子節(jié)點上,而非葉子節(jié)點上只存儲key值信息,這樣可以大大加大每個節(jié)點存儲的key值數(shù)量,降低B+Tree的高度。
- B+Tree相對于B-Tree有幾點不同:
- 非葉子節(jié)點只存儲鍵值信息;
- 所有葉子節(jié)點之間都有一個鏈指針;
- 數(shù)據(jù)記錄都存放在葉子節(jié)點中
- 將上一節(jié)中的B-Tree優(yōu)化,由于B+Tree的非葉子節(jié)點只存儲鍵值信息,假設每個磁盤塊能存儲4個鍵值及指針信息,則變成B+Tree后其結構如下圖所示:
- 通常在B+Tree上有兩個頭指針,一個指向根節(jié)點,另一個指向關鍵字最小的葉子節(jié)點,而且所有葉子節(jié)點(即數(shù)據(jù)節(jié)點)之間是一種鏈式環(huán)結構。
- 因此可以對B+Tree進行兩種查找運算:一種是對于主鍵的范圍查找和分頁查找,另一種是從根節(jié)點開始,進行隨機查找。
- 可能上面例子中只有22條數(shù)據(jù)記錄,看不出B+Tree的優(yōu)點,下面做一個推算:
- InnoDB存儲引擎中頁的大小為16KB,一般表的主鍵類型為INT(占用4個字節(jié))或BIGINT(占用8個字節(jié))
- 指針類型也一般為4或8個字節(jié),也就是說一個頁(B+Tree中的一個節(jié)點)中大概存儲16KB/(8B+8B)=1K個鍵值(因為是估值為方便計算,這里的K取值為10
^ 3)。 - 也就是說一個深度為3的B+Tree索引可以維護10^3 * 10^3 * 10^3 = 10億 條記錄。
- 實際情況中每個節(jié)點可能不能填充滿,因此在數(shù)據(jù)庫中,B+Tree的高度一般都在2-4層。
- MySQL的InnoDB存儲引擎在設計時是將根節(jié)點常駐內存的,也就是說查找某一鍵值的行記錄時最多只需要1~3次磁盤I/O操作。
- B+Tree性質
- 通過上面的分析,我們知道IO次數(shù)取決于b+數(shù)的高度h,假設當前數(shù)據(jù)表的數(shù)據(jù)為N,每個磁盤塊的數(shù)據(jù)項的數(shù)量是m,則有h=㏒(m+1)N,當數(shù)據(jù)量N一定的情況下,m越大,h越小;
- 而m = 磁盤塊的大小 / 數(shù)據(jù)項的大小,磁盤塊的大小也就是一個數(shù)據(jù)頁的大小,是固定的,如果數(shù)據(jù)項占的空間越小,數(shù)據(jù)項的數(shù)量越多,樹的高度越低。
- 這就是為什么每個數(shù)據(jù)項,即索引字段要盡量的小,比如int占4字節(jié),要比bigint8字節(jié)少一半。
- 這也是為什么b+樹要求把真實的數(shù)據(jù)放到葉子節(jié)點而不是內層節(jié)點,一旦放到內層節(jié)點,磁盤塊的數(shù)據(jù)項會大幅度下降,導致樹增高。
- 當數(shù)據(jù)項等于1時將會退化成線性表。
- 當b+樹的數(shù)據(jù)項是復合的數(shù)據(jù)結構,比如(name,age,sex)的時候,b+數(shù)是按照從左到右的順序來建立搜索樹的
- 比如當(張三,20,F)這樣的數(shù)據(jù)來檢索的時候,b+樹會優(yōu)先比較name來確定下一步的所搜方向,如果name相同再依次比較age和sex,最后得到檢索的數(shù)據(jù);
- 但當(20,F)這樣的沒有name的數(shù)據(jù)來的時候,b+樹就不知道下一步該查哪個節(jié)點,因為建立搜索樹的時候name就是第一個比較因子,必須要先根據(jù)name來搜索才能知道下一步去哪里查詢。
- 比如當(張三,F)這樣的數(shù)據(jù)來檢索時,b+樹可以用name來指定搜索方向,但下一個字段age的缺失,所以只能把名字等于張三的數(shù)據(jù)都找到,然后再匹配性別是F的數(shù)據(jù)了,
- 這個是非常重要的性質,即索引的最左匹配特性。
總結
以上是生活随笔為你收集整理的MySQL基础总结(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LFU缓存详解
- 下一篇: MySQL基础总结(二)