1. 程式人生 > >MySQL基本原理和使用技巧

MySQL基本原理和使用技巧

本文是我在大半年前在前公司做團隊分享時的一個文件,寫得比較挫,當時分享講了2個小時,自己感覺講得還可以。最近前同事跑來問我還有沒有文件儲存,翻了舊電腦和硬碟才找出來,於是就想著分享一下。


一、MySQL整體結構

  • 伺服器層(負責客戶端連線、授權認證、安全、執行緒管理等)

  • 核心層(快取查詢、解析器、查詢優化器、函式)(儲存過程,觸發器,檢視)

  • 儲存引擎層(MyISAM、InnoDB、Memory、Merge,負責資料的儲存和提取)
    在這裡插入圖片描述

資料庫的全球排名情況
https://db-engines.com/en/ranking

本次講的大多是INNODB

mysql太多內容可講,每個點都一次分享都講不完。
沒有理解核心實現時的無法知道mysql怎麼工作,只知道儲存。
帶大家從外而內看透MySQL。
這個整體結構類似於springMvc中的controller service dao

  • Connectors:不同語言中與 SQL 的互動
  • Management Serveices & Utilities:系統管理和控制工具
  • Connection Pool:連線池
  • SQL Interface:SQL 介面(提供給儲存引擎層,類似於面向介面程式設計,SPI等)
  • Parser:解析器
  • Optimizer:查詢優化器
  • Cache 和 Buffer:查詢快取
  • Engine:儲存引擎

MyISAM和INNODB的區別

1、Innodb最大的特點: 支援事務處理與外來鍵和行級鎖
2、索引實現方式不同,MyISAM的索引和資料是分開的,並且索引是有壓縮的,記憶體使用率就對應提高了不少InnoDB 中不儲存表的具體行數,也就是說,執行select count() from table
3、對於AUTO_INCREMENT型別的欄位,InnoDB中必須包含只有該欄位的索引,但是在MyISAM表中,可以和其他欄位一起建立聯合索引
4、DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5、InnoDB 中不儲存表的具體行數,也就是說,執行select count(

) from table

關於MyISAM和InnoDB的其他相關
1、讀多寫少的,MyISAM的讀效能是比Innodb強不少
2、MySQL 4.0以上 myisam引擎就支援了full text search 全文搜尋
3、mysql版本號已經大於5.6.4了也就支援了innodb的全文搜尋

一條查詢語句的執行過程

二、MySQL的資料結構和原理

Questions

  1. MySQL通過什麼資料結構實現?

  2. 為什麼要用這種資料結構實現?

  3. 我們如何最大化這種特性?如何利用這種特性來優化我們的資料庫設計和查詢?

  • 常用的資料結構
線性結構:陣列、連結串列、雜湊表

樹形結構:二叉樹(平衡二叉樹、二叉查詢樹、完全二叉樹)、2-3樹、紅黑樹、B樹

圖形結構:有向圖、無向圖

二叉樹

  1. 若任意節點的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;

  2. 若任意節點的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;

  3. 任意節點的左、右子樹也分別為二叉查詢樹。

  4. 沒有鍵值相等的節點(no duplicate nodes)。

二分查詢\二叉樹查詢,時間複雜度o(lgn)

2-3樹

  1. 對於3節點,該節點儲存兩個key及對應value,以及三個指向左中右的節點

  2. 在最壞的情況下,也就是所有的節點都是2-node節點,查詢效率為lgN

  3. 在最好的情況下,所有的節點都是3-node節點,查詢效率為log3N約等於0.631lgN

在最壞的情況下,也就是所有的節點都是2-node節點,查詢效率為lgN

在最好的情況下,所有的節點都是3-node節點,查詢效率為log3N約等於0.631lgN

紅黑樹

  1. 紅色節點向左傾斜

  2. 一個節點不可能有兩個紅色連結

  3. 整個書完全黑色平衡,即從根節點到所以葉子結點的路徑上,黑色連結的個數都相同。

紅黑樹是2-3樹的一種簡單高效的實現

B樹

  1. 每一個節點都包含資料,元素離根節點餘越近訪問越快


B+樹

  1. 內部節點上不包含資料資訊

  2. 葉子結點都是相連的

對於一顆節點為N度為M的子樹,查詢和插入需要logM-1N ~ logM/2N次比較。這個很好證明,對於度為M的B樹,每一個節點的子節點個數為M/2 到 M-1之間,所以樹的高度在logM-1N至logM/2N之間。

這種效率是很高的,對於N=62*1000000000個節點,如果度為1024,則logM/2N <=4,即在620億個元素中,如果這棵樹的度為1024,則只需要小於4次即可定位到該節點,然後再採用二分查詢即可找到要找的值。

B+樹效果演示

B樹和B+樹的排序圖區別

  • 有哪些可能被用來實現MySQL的資料結構

有了上面的資料結構知識,可以知道MySQL會利用什麼資料結構實現了嗎?

磁碟上資料必須用一個三維地址唯一標示:柱面號、盤面號、塊號(磁軌上的盤塊)。

磁碟讀取資料是以盤塊(block)為基本單位的,一個block為4k

  • InnoDB索引實現

主鍵索引

非主鍵索引

基於B+樹的資料結構給出的建議:

  1. 表的主鍵儘量用自增ID,不用隨機生成的
  2. 某些查詢可以使用覆蓋索引的,則可以減少一次回表查詢

三、MySQL隔離級別和MVCC實現原理

  • Read Uncommitted(讀未提交)
  • Read Committed(讀已提交)
  • Repeatable Read(可重複讀)
  • Serializable(序列化)
每一行資料維護兩個額外欄位 刪除版本號和更新版本號

在這裡插入圖片描述

四、MySQL的鎖機制

常用的鎖的方式

  • select … lock in share mode
  • select … for update

樂觀鎖的使用例子:

update trade_id_log set max_trade_id=#maxTradeId# where owner_id=#ownerId# and max_trade_id = #originMaxTradeId#

看下面的SQL是否加鎖,如何加鎖:

SQL1:select * from t1 where id = 10;

SQL2:delete from t1 where id = 10;

先拋兩個名詞:記錄鎖、間隙鎖 看下面幾種情況是怎麼加鎖的

1.id列是主鍵,RC隔離級別

(X鎖是排他鎖)

2.id列是二級非唯一索引,RC隔離級別

3.id列是二級非唯一索引,RR隔離級別

4.id無索引,RR隔離級別

5.Serializable隔離級別

Serializable隔離級別,影響的是SQL1:select * from t1 where id = 10;

6.思考一下這幾種情況

(1)id列是二級唯一索引,RC隔離級別;

(2)id列上沒有索引,RC隔離級別;

(3)id列是主鍵,RR隔離級別;

(4)id列是二級唯一索引,RR隔離級別;

7.分析一條複雜的SQL的加鎖方式(RR隔離級別)

–>

五、MySQL使用技巧

1.sql查詢優化,瞭解explain

 (1)分頁問題:使用者需要檢視第50000頁的100條資料
解決方案一:
先通過覆蓋索引查對應的分頁資料的主鍵ID,再通過主鍵ID去查資料

解決方案二: 
業務優化,不讓使用者選擇;或者只能上/下一頁翻動

explain select SQL_NO_CACHE * from product limit 5000000,100 
\# 掃描的行:6512596

explain select SQL_NO_CACHE * from product where id > 7391753 limit 0,100 

\# 掃描的行:3256298,記錄上一頁最後一條資料id,用於下一次的搜尋

(2)Group by優化
GROUP BY 預設會使用分組欄位排序(可能會檔案排序),取消排序使用order by null

如:explain select status,count(status) from trade30 group by status ;

改寫成 explain select status,count(status) from trade30 group by status order by null ;

2.ip儲存

select inet_aton("192.168.52.100");

select inet_ntoa(3232248932);

3.mysql程式 mysql函式(使用案例:自定義大量資料入庫(模擬陳胤的product資料))

自定義函式:生成隨機字串

DELIMITER &&
CREATE FUNCTION `randstring`(n INT) RETURNS varchar(255) 
BEGIN
 DECLARE chars_str varchar(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
 DECLARE return_str varchar(255) DEFAULT '';
 DECLARE i INT DEFAULT 0;
 WHILE i < n DO
 SET return_str = concat(return_str,substring(chars_str , FLOOR(1 + RAND()*62 ),1));
 SET i = i +1;
 END WHILE;
 RETURN return_str;
END
&&


4.自定義hash索引(crc32函式 crc64函式)使用案例:精確查詢某個固定的字串

CREATE TABLE `crc` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `article` varchar(512) DEFAULT NULL,
 `value` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `IDX_V` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

set @aa = "adsfhaklshfjdsafhasdkfyuqwo4623703241213846231891421354961238472318947123elrbmanvcuixgqwbelfjasdkcgsavdlfbasdkchadgsliubfja.sdkvhgvsi";

insert into crc VALUES(null,@aa,CRC32(@aa));

select * from crc where value = crc32(@aa);

5.避免資料庫插入重複記錄

(1)insert ignore into person (id,name,phone) VALUES (20,‘111’,‘12’);

(2)REPLACE into person (id,name,phone) VALUES (20,‘20’,‘20’);

(3)insert into person (id,name,phone) VALUES (32,‘3232’,‘3232’) ON DUPLICATE KEY UPDATE name=‘323232’;

6.樂觀鎖的使用

update trade_id_log set max_trade_id=#maxTradeId# where owner_id=#ownerId# and max_trade_id = #originMaxTradeId#

7.檢視的使用

刪除檢視
drop view if exists user_view;

建立檢視
create view user_view as select uid,uname,mobile from user_account;

查詢檢視
select * from user_view;

作者推薦部落格

  1. Data Structures & Algorithms

  2. MySQL索引背後的資料結構及演算法原理

  3. MySQL加鎖處理分析