日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL基础总结(一)

發(fā)布時間:2024/4/11 数据库 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL基础总结(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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。
--查看MySQL 數(shù)據(jù)保存在哪里: show variables like 'data%'
  • 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)建索引:
CREATE [UNIQUE] INDEX indexName ON mytable(username(length));

如果是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) 該語句添加一個主鍵,這意味著索引值必須是唯一的,且不能為NULLALTER 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 中可通過如下命令查看頁的大小:
show variables like 'innodb_page_size';
  • 而系統(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基础总结(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。