🌈MySQL真的就CRUD嗎?✨來看看2k和12k之間的差距(上)

這是我參與8月更文挑戰的第11天,活動詳情查看:8月更文挑戰mysql

🌈往期回顧

    感謝閱讀,但願能對你有所幫助,博文如有瑕疵請在評論區留言或在主頁我的介紹中添加我私聊我,感謝每一位小夥伴不吝賜教。我是XiaoLin,既會寫bug也會唱rap的男人算法

1、MySql 的用戶和權限管理

1.一、MySQL的用戶管理

1.1.一、相關命令

命令 描述 備註
create user xiaolin identified by '123456'; 建立名稱爲xiaolin的用戶,密碼爲123456
select host,user,password,select_priv,insert_priv,drop_priv from mysql.user; 查看用戶和權限的相關信息
set password = password('123456') 修改其餘用戶的密碼 全部經過 user 表的修改,必須用 flush privileges;命令才能生效
update mysql.user set user = 'zs' where user = 'xiaolin' 修改用戶名 全部經過 user 表的修改,必須用 flush privileges;命令才能生效
drop user xiaolin 刪除用戶 不要經過delete from user where user = 'xiaolin'進行刪除,系統會有殘留信息保存

1.1.二、詳解

image-20210524101653451

host

    host表示鏈接類型。sql

  1. %:表示全部遠程經過TCP方式鏈接。
  2. 127.0.0.1:經過指定IP進行的TCP方式的鏈接。
  3. 機器名:經過指定網絡中的機器名進行的TCP方式的鏈接。
  4. ::1:IPV6的本地IP地址,等同於IPV4的127.0.0.1
  5. localhost 本地方式經過命令行方式的鏈接 ,好比 mysql -u xxx -p 123xxx 方式的鏈接。

user

    user表示用戶名,同一用戶經過不一樣方式鏈接的權限是不同的。數據庫

password

    這裏顯示的是明文密碼經過哦MYSQLSHA1加密算法加密後獲得的密文密碼,是不可逆的,mysql 5.7 的密碼保存到 authentication_string 字段中再也不使用 password 字段。緩存

select_priv , insert_priv等

    表示該用戶所擁有的權限。安全

1.二、MySQL的權限管理

1.2.一、授予權限

    咱們能夠經過命令來授予用戶權限,該權限若是發現沒有該用戶,則會直接新建一個用戶。服務器

    格式爲:markdown

grant 權限 1,權限 2,…權限 n on 數據庫名稱.表名稱 to 用戶名@用戶地址 identified by‘鏈接口令
複製代碼

    示範:網絡

# 給 xiaolin 用戶用本地命令行方式下,授予 user 這個庫下的全部表的插刪改查的權限。
grant select,insert,delete,drop on user.* to xiaolin@localhost;

# 授予經過網絡方式登陸的的 xiaolin 用戶 ,對全部庫全部表的所有權限,密碼設爲 123.
grant all privileges on *.* to xiaolin@'%' identified by '123';
複製代碼

1.2.二、查看權限

    咱們可使用命令來查看當前用戶的權限。數據結構

show grants;
複製代碼

1.2.三、收回權限

    咱們可使用命令來收回用戶的權限,權限收回後,必須用戶從新登陸後,才能生效。

revoke
[權限 1,權限 2,…權限 n] on 庫名.表名 from 用戶名@用戶地址 ;
複製代碼

示範:

# 收回全庫全表的全部權限
REVOKE ALL PRIVILEGES ON mysql.* FROM joe@localhost;

# 收回 mysql 庫下的全部表的插刪改查權限
REVOKE select,insert,update,delete ON mysql.* FROM xiaolin@localhost;
複製代碼

2、MySQL邏輯架構

2.一、總體架構圖

image-20210524141914538

    和其它數據庫相比,MySQL 有點不同凡響,它的架構能夠在多種不一樣場景中應用併發揮良好做用。主要體如今存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構能夠根據業務的需求和實際須要選擇合適的存儲引擎。

2.二、MySQL分層

MySql大概分爲四層:

MySQL分層

2.2.一、鏈接層

    最上層是一些客戶端和鏈接服務,包含本地 sock 通訊和大多數基於客戶端/服務端工具實現的相似於 tcp/ip 的通訊。主要完成一些相似於鏈接處理、受權認證、及相關的安全方案。在該層上引入了線程池的概念,爲經過認證安全接入的客戶端提供線程。一樣在該層上能夠實現基於 SSL 的安全連接。服務器也會爲安全接入的每一個客戶端驗證它所具備的操做權限。

2.2.二、服務層

    服務層提供各類用戶使用的接口,同時提供SQL優化器,對用戶傳進來的SQL語句進行優化。他有幾個組件。

組件名 描述
Management Serveices & Utilities 系統管理和控制工具
SQL Interface SQL 接口。接受用戶的 SQL 命令,而且返回用戶須要查詢的結果。好比 select from就是調用 SQL Interface
Parser 解析器。 SQL 命令傳遞到解析器的時候會被解析器驗證和解析
Optimizer 查詢優化器。SQL 語句在查詢以前會使用查詢優化器對查詢進行優化,好比有where 條件時,優化器來決定先投影仍是先過濾。
Cache 和 Buffer 查詢緩存。若是查詢緩存有命中的查詢結果,查詢語句就能夠直接去查詢緩存中取數據。這個緩存機制是由一系列小緩存組成的。好比表緩存,記錄緩存,key 緩存,權限緩存等

2.2.三、引擎層

    存儲引擎層,存儲引擎真正的負責了 MySQL 中數據的存儲和提取,服務器經過 API 與存儲引擎進行通訊。不一樣的存儲引擎具備的功能不一樣,這樣咱們能夠根據本身的實際須要進行選取。

2.2.四、存儲層

    數據存儲層,主要是將數據存儲在運行於裸設備的文件系統之上,並完成與存儲引擎的交互。

2.三、MySQL的查詢流程

    mysql 的查詢流程大體是:

  1. MySQL客戶端經過協議與MySQL服務器創建鏈接,發送查詢語句。
  2. 服務器收到了查詢語句以後,會先去檢查查詢緩存,這個緩存存儲了SELECT語句以及相應的查詢結果集。若是命中(查詢結果已經位於緩存中)服務器就不會再對查詢進行解析、優化、執行,他作的僅僅是將緩存中的結果直接返回給用戶,大大提高了性能。若是沒有命中緩存的話,將會進行第三步。
  3. 接下來進入的是語法解析器和預處理,首先MySQL經過關鍵字將SQL進行解析,並生成一顆對應的解析樹。MySQL解析器將使用MySQL語法規則驗證解析查詢,預處理器則根據一些MySQL規則進一步檢查解析是否合法。
  4. 接着到了查詢優化器,解析樹由優化器轉化爲執行計劃。一條查詢能夠有不少種執行方式,可是最後都返回相同的結果,優化器的做用就是找到其中最好的執行計劃。
  5. 最後交有存儲引擎進行執行返回給客戶端。

MySQL執行流程

2.四、MySQL的執行順序

    咱們手寫一條完整的SQL大概是這樣寫的。

SELECT DISTINCT
    < select_list >
FROM
    < left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
    < where_condition >
GROUP BY
    < group_by_list >
HAVING
    < having_condition >
ORDER BY
    < order_by_condition >
LIMIT < limit_number >
複製代碼

    然而它的執行順序是這樣的.。

FROM <left_table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT
DISTINCT <select_list>
ORDER BY <order_by_condition>
LIMIT <limit_number>
複製代碼

image-20210524171827989

2.五、MyISAM 和 InnoDB

對比項 MyISAM InnoDB
外鍵 不支持 支持
事務 不支持 支持
行表鎖 表鎖,即便操做一條記錄也會鎖住整張表,不適合高併發操做 行鎖,操做時只鎖住某一行,不對其餘行有影響,適合高併發操做
緩存 只緩存索引不緩存真實數據 不只僅緩存索引還緩存真實數據,對內存要求較高,並且內存大小對性能有決定性的影響

3、索引

3.一、索引的概述

3.1.一、索引是什麼

    MySQL 官方對索引的定義爲:索引(Index)是幫助 MySQL 高效獲取數據的數據結構。能夠獲得索引的本質:索引是數據結構。能夠簡單理解爲排好序的快速查找數據結構。

    在數據以外,數據庫系統還維護着知足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就能夠在這些數據結構上實現高級查找算法。這種數據結構,就是索引。

image-20210524211732444

    左邊是數據表,一共是兩列七條數據,最左邊的是數據記錄的物理地址。爲了加快 Col2 的查找,能夠維護一個右邊所示的二叉查找樹,每一個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就能夠運用二叉查找在必定的複雜度內獲取到相應數據,從而快速的檢索出符合條件的記錄。

    通常來講索引自己也很大,不可能所有存儲在內存中,所以索引每每以索引文件的形式存儲的磁盤上。

3.二、索引的優缺點

3.2.一、優勢

  1. 提升數據檢索的效率,下降數據庫的IO成本。
  2. 經過索引列對數據進行排序,下降數據排序的成本,下降了CPU的消耗。

3.2.二、缺點

  1. 雖然索引大大提升了查詢速度,同時卻會下降更新表的速度,如對錶進行INSERT、UPDATE和DELETE。由於更新表時,MySQL不只要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整由於更新所帶來的鍵值變化後的索引信息。
  2. 實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,因此索引列也是要佔用空間的。

3.二、Btree 索引

3.2.一、初始化介紹

    MySQL 使用的是 Btree 索引。一顆B樹,淺藍色的塊咱們稱之爲一個磁盤塊,能夠看到每一個磁盤塊包含幾個數據項(深藍色所示)和指針(黃色所示)。

image-20210524212305101

    磁盤塊 1 包含數據項 17 和 35,包含指針 P一、P二、P3,P1 表示小於 17 的磁盤塊,P2 表示在 17 和 35 之間的磁盤塊,P3 表示大於 35 的磁盤塊。

    真實的數據存在於葉子節點即 三、五、九、十、1三、1五、2八、2九、3六、60、7五、7九、90、99。

    非葉子節點只不存儲真實的數據,只是爲了做爲分隔線,存儲指引搜索方向的數據項,如 1七、35 並不真實存在於數據表中。

3.2.二、查找過程

    若是要查找數據項 29,那麼首先會把磁盤塊 1 由磁盤加載到內存,此時發生一次 IO。

    在內存中用二分查找肯定 29在 17 和 35 之間,鎖定磁盤塊 1 的 P2 指針,內存時間由於很是短(相比磁盤的 IO)能夠忽略不計。經過磁盤塊 1的 P2 指針的磁盤地址把磁盤塊 3 由磁盤加載到內存,發生第二次 IO。

    29 在 26 和 30 之間,鎖定磁盤塊 3 的 P2 指針,經過指針加載磁盤塊 8 到內存,發生第三次 IO,同時內存中作二分查找找到 29,結束查詢,總計三次 IO。

    3層的B樹能夠表示上百萬的數據,若是上百萬的數據查找只須要三次 IO,性能提升將是巨大的。

    若是沒有索引,每一個數據項都要發生一次 IO,那麼總共須要百萬次的 IO,顯然成本很是很是高。

3.三、B+tree 索引

    咱們能夠看到BTree結構圖中,每一個節點不只僅包含key值,同時還有data值,每個頁的存儲空間是有限的,若是data數據較大時會致使每一個節點(即每個頁)能存儲的key數量很小,當存儲的數據量很大的時候會致使BTree的深度很深,增大了查詢時磁盤I/O的次數。

    而在B+Tree中,全部數據記錄節點都是按照鍵值大小順序放在同一層的葉子節點上,而非葉子節點只存儲key信息,這樣能夠大大增長每一個節點存儲的key值的數量,下降B+Tree的高度。

    實際狀況中每一個節點可能不能填滿,在數據庫中,B+Tree的高度通常在24層之間,MySQL的InnoDB存儲引擎在設計時是將根節點常駐內存的(不動用磁盤I/O,直接上內存找),也就是說查找某一鍵值行記錄時最多隻須要13次磁盤I/O操做。

image-20210524212903582

3.四、B+Tree 與 B-Tree 的區別

  1. B-樹的關鍵字和記錄是放在一塊兒的,葉子節點能夠看做外部節點,不包含任何信息;B+樹的非葉子節點中只有關鍵字和指向下一個節點的索引,記錄只放在葉子節點中。
  2. 在 B-樹中,越靠近根節點的記錄查找時間越快,只要找到關鍵字便可肯定記錄的存在;而 B+樹中每一個記錄的查找時間基本是同樣的,都須要從根節點走到葉子節點,並且在葉子節點中還要再比較關鍵字。從這個角度看好像B-樹的性能1是要比B+樹的性能要高,而在實際應用中確實B+樹的性能更好一些。由於B+樹的非葉子節點不存放實際的數據,這樣每一個11節點1可容納的元素個數比B-樹多,可是依次磁盤訪問的時間至關於成千上百次內存比較的時間,所以在實際中B+樹性能更好,並且B+樹的葉子節點1是使用指針鏈接在一塊兒,方便順序遍歷。

3.五、爲何B+樹比 B樹更適合實際應用

  1. B+樹的磁盤讀寫代價更低:B+樹的內部結點並無指向關鍵字具體信息的指針。所以其內部結點相對 B 樹更小。若是把全部同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的須要查找的關鍵字也就越多。相對來講 IO 讀寫次數也就下降了。
  2. B+樹的查詢效率更加穩定:因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。

3.六、聚簇索引和非聚簇索引

  1. 聚簇索引:將數據存儲與索引放到了一塊,索引結構的葉子節點保存了行數據,聚簇索引默認是主鍵。
  2. 非聚簇索引:也稱爲輔助索引,將數據與索引分開存儲,索引結構的葉子節點指向了數據對應的位置。非聚簇索引存儲的再也不是行的物理位置,而是主鍵值,輔助索引訪問數據老是須要二次查找。不存儲物理位置的緣由是當數據發生增刪改的時候,物理位置可能會發生改變,萬一發生了改變,那麼還須要維護非聚簇索引。

image-20210525222603449

  • 聚簇索引查找:將主鍵組織到一個B+Tree樹中,而行數據就存儲在葉子節點上,若使用'where id = 14'這樣的條件查找主鍵時,則按照B+Tree的檢索算法便可查找到對應的葉子節點,從而得到行數據。
  • 若對name(輔助索引)列進行條件搜索則須要兩個步驟:
    1. 第一步先在輔助索引B+Tree中檢索name,到達其葉子節點對應的主鍵。
    2. 使用主鍵在主索引B+Tree中再執行一次B+Tree檢索操做,最終到達葉子節點便可獲取整行數據。

3.6.一、聚簇索引的好處

  1. 因爲行數據和聚簇索引的葉子節點存儲在一塊兒,同一頁中會有多條行數據,訪問統一數據頁不一樣記錄時,已經把頁加載到了buffer(緩存器),再次訪問時,會在內存中完成訪問,沒必要訪問磁盤。這樣主鍵和行數據時一塊兒載入內存的,找到葉子節點就能夠馬上將數據返回了,若是按照主鍵ID來組織數據的話,得到數據更快。
  2. 輔助索引的葉子節點是存儲主鍵的,而不是數據的存放地址。好處是當行數據發生改變時,索引樹節點也是須要分裂變化的,另外一個好處是由於輔助索引存放的是主鍵值,減小了輔助索引佔用的存儲空間大小。

3.6.二、聚簇索引的限制

  1. 對於 mysql 數據庫目前只有 innodb 數據引擎支持聚簇索引,而 Myisam 並不支持聚簇索引。
  2. 因爲數據物理存儲排序方式只能有一種,因此每一個 Mysql 的表只能有一個聚簇索引。通常狀況下就是該表的主鍵。
  3. 爲了充分利用聚簇索引的聚簇的特性,**因此 innodb 表的主鍵列儘可能選用有序的順序 id,而不建議用無序的 id,好比 uuid 這種。**若是id比較大的1話,能夠選擇雪花算法1得出的id。
  4. 建議使用int自增的類型,方便排序且默認會在索引樹末尾增長主鍵值,對索引樹結構影響最小。聚簇索引的數據的物理存放順序是一致的,由於索引是相鄰的,那麼對應的數據必定也是相鄰地存放在磁盤上的,若是主鍵不是自增id,那麼它會不斷地調整物理地址、分頁,但若是是自增,那麼他只需一頁頁地寫索引結構相對緊湊,磁盤碎片較少,效率高。

3.七、索引的分類

3.7.一、單值索引

3.7.1.一、概述

    單值索引指一個索引只包含單個列,一個表能夠有多個單列索引。

3.7.1.二、語法

# 隨着表的創建一塊兒創建
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id), KEY (customer_name) );

# 單獨建單值索引
CREATE INDEX idx_customer_name ON customer(customer_name);
複製代碼

3.7.二、惟一索引

3.7.2.一、概述

    惟一索引指的是索引列必須惟一,可是容許有空值,且只能有一個。

3.7.2.二、語法

# 隨着表的創建一塊兒創建
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id), KEY (customer_name), UNIQUE (customer_no) );

# 單獨建惟一索引
CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);
複製代碼

3.7.三、主鍵索引

3.7.3.一、概述

    設定爲主鍵後數據庫會自動創建索引,innodb爲聚簇索引,主鍵索引列值不能爲空。

3.7.3.二、語法

# 隨表一塊兒建索引
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id) );

# 單獨建主鍵索引
ALTER TABLE customer add PRIMARY KEY customer(customer_no);

# 刪除建主鍵索引
ALTER TABLE customer drop PRIMARY KEY ;

# 若是須要修改建主鍵索引,必須先刪除掉(drop)原索引,再新建(add)索引
複製代碼

3.7.四、複合索引

    他會符合兩個原則:

  1. 最左匹配原則。
  2. MySQL引擎在查詢時爲了更好的利用索引,在查詢過程當中會動態調整查詢字段的順序,以便於更好地利用索引。

3.7.4.一、概述

    複合索引是一個索引包含多個列。

3.7.4.二、語法

# 隨表一塊兒建索引
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200), PRIMARY KEY(id), KEY (customer_name), UNIQUE (customer_name), KEY (customer_no,customer_name) );

# 單獨建索引
CREATE INDEX idx_no_name ON customer(customer_no,customer_name);
複製代碼

3.八、索引的建立時機

3.8.一、適合建立索引的時機

  • 主鍵自動創建惟一索引。
  • 頻繁做爲查詢條件的字段應該建立索引。
  • 查詢中與其餘表關聯的字段,外鍵關係創建索引。
  • 單鍵/組合索引面臨選擇的適合,通常選擇組合索引性價比更高。
  • 查詢中排序的字段,排序字段若經過1索引去訪問將大大提升排序的1速度。
  • 查詢中統計或者分組字段。

3.8.二、不適合建立索引的狀況

  • 表記錄太少。
  • 常常增刪改的表或者字段。
  • where條件裏用不到的字段不建立索引。

3.九、索引的基本操做

3.9.一、主鍵索引

    主鍵索引是在建表時自動建立的。

建表,主鍵自動建立主鍵索引

create table t_user(id varchar(20) primary key,name varchar(20));
複製代碼

查看索引

show index from t_user;
複製代碼

image-20210604150311834

3.9.二、單列索引

創表的時候一塊兒建立索引

# 在建表的時候字段後面用key(列名)來建立索引,可是咱們沒辦法指定索引名,默認索引名和列名一致。
create table t_user(id varchar(20) primary key , name varchar(20 , key(name)))
複製代碼

建立完表之後加索引

# 語法格式
create index 索引名 on 表名(列名);

# 示範
create index index_name on t_user(name);
複製代碼

image-20210604150718129

刪除索引

# 語法格式
drop index 索引名 on 表名;

# 示範
drop index index_name on t_user;
複製代碼

3.9.三、惟一索引

建表的時候建立索引

# 在建表的時候字段後面用unique(列名)來建立索引,可是咱們沒辦法指定索引名,默認索引名和列名一致。
create table t_user(id varchar(20) primary key , name varchar(20) , unique(name) );
複製代碼

建立表以後建立索引

# 格式
create unique index 索引名 on 表名(列名);

# 示範
create unique index index_name on t_user(name);
複製代碼

3.9.四、複合索引

建表的時候建立索引

# 在建表的時候字段後面用key(列名1,列名2...)來建立索引,可是咱們沒辦法指定索引名,默認索引名和列名一致。
create table t_user (id varchar(20) primary key , name varchar(20) , age int , key(name , age) );
複製代碼

建表以後建立

# 語法格式
create index 索引名 on 表名(列名1,列名2...);

# 示範
create index index_name_age on t_user (name , age);
複製代碼
相關文章
相關標籤/搜索