MySQL核心知識學習之路(6)

作爲一個後端工程師,想必沒有人沒用過數據庫,跟我一起復習一下MySQL吧,本文是我學習《MySQL實戰45講》的總結筆記的第六篇,總結了MySQL的InnoDB引擎相關的實踐使用問題。

上一篇:MySQL核心知識學習之路(5)

1 MySQL爲什麼有時會"抖"一下?

啥是抖?

抖即不穩定,一個SQL語句平時速度挺快的,偶爾卻會慢一下,稱之爲“抖”

爲何會抖?

因爲InnoDB引擎在後臺刷“髒頁”佔用了IO資源。

所謂“髒頁”,就是當內存數據頁跟磁盤數據頁內容不一致的時候就是“髒頁”。

由於MySQL使用了WAL機制(Write-ahead logging 預寫式日誌),會將數據庫的隨機寫轉化爲順序寫,提高讀寫性能,但副作用就是“髒頁”

所謂“乾淨頁”,就是當內存數據寫入磁盤後,內存和磁盤上的數據頁的內容一致了。

抖的影響?

會造成系統不穩定,性能突然下降,對業務端不友好。

如何防抖?

(1)設置合理參數配置,如 innodb_io_capacity 設置成磁盤的IOPS值。

平時多關注髒頁比例(innodb_max_dirty_pages_pct,默認值75%),不要超過75%

2 爲何表數據刪掉一半後表文件大小不變?

表文件不變的原因?

因爲delete命令指示將記錄的位置 或 數據頁 標記爲了“可複用”,並沒有收回表空間

這些被標記爲“可複用”但還未被使用的空間被稱之爲“空洞”。

 

圖片來源:林曉斌《MySQL實戰45講》

使用delete命令刪除數據就會產生空洞,被標記爲“可複用”。而使用insert命令插入數據可能引起頁分裂,也可能產生空洞。

 

圖片來源:林曉斌《MySQL實戰45講》

表數據如何存放?

表數據既可以存放在共享表空間裏,也可以放在單獨的文件(.ibd)中。

由參數 innodb_file_per_table 控制:

  • = OFF,存放在系統共享表空間

  • = ON,存放在單獨的.ibd文件中

  • MySQL 5.6.6 開始,默認值就是ON

如何讓刪除數據後的表文件變小?

重建表,消除因爲進行大量的更新操作而產生的空洞。下圖是使用alter table t engine=InnoDB重建表的示意圖,MySQL 會自動完成轉存數據、交換表名、刪除舊錶的操作。 

圖片來源:林曉斌《MySQL實戰45講》

如何正確重建表:

  • alter table t engine=InnoDB

  • optimize table t (等同於 recreate + analyze)

  • truncate table t (等同於 drop + create)

Online DDL

MySQL 5.6開始引入了Online DDL,支持在重建表過程中對錶做更新操作。

 

圖片來源:林曉斌《MySQL實戰45講》

其實現原理如下:

  • 在生成臨時文件過程中,通過row log記錄更新操作,然後再應用到臨時文件。

  • 最後用臨時文件整體替換表的數據文件。

  • alter語句在啓動時獲取MDL寫鎖,但在真正拷貝數據之前退化爲MDL讀鎖,而MDL讀鎖不會阻塞更新操作。

適用場景:可以考慮在業務低峯期使用

在MySQL 5.5及之前版本,這個命令會阻塞DML。

3 count(*)爲何這麼慢?

不同引擎對於count(*)的實現方式

select count(*) from t

MyISAM引擎將表的總行數存在了磁盤上,因此效率很高

InnoDB引擎則每次都需要將數據一行一行地從引擎中讀出來進行累積計數,因此存在性能問題

那麼,問題來了:爲什麼InnoDB不跟MyISAM一樣設計?

InnoDB的事務隔離級別默認是可重複讀,而MyISAM不支持事務

那麼,第二個問題:能用show table status中的TABLE_ROWS代替嗎?

不能,因爲它是通過採樣估算的,存在40%~50%的誤差。

自己計數的實現方法

方式1:用緩存系統如Redis來保存計數,存在丟失更新、邏輯上不精確的問題,因此不建議使用。

方式2:用數據庫表來保存計數,不會丟失更新和不精確,建議使用

不同count()用法對比

首先,弄清楚的count()的含義。

count():一個聚合函數,對於返回的結果集,一行行地判斷,如果count函數的參數不是NULL,累計值就加1,否則不加。最後返回累計值。

其次,直接給出結論。

按照效率排序:count(字段)<count(主鍵 id)<count(1)≈count(*)。

建議儘量使用 count(*),因爲MySQL對count(*)專門進行了優化

4 小結

本文總結了MySQL的InnoDB引擎相關的實踐使用問題,包括MySQL爲什麼有時候會不穩定的“抖”一下、爲何表數據刪除了一半但表文件大小沒變 和 爲何 count(*)會很慢。

參考資料

林曉斌(丁奇),《MySQL實戰45講》

👇掃碼訂閱《MySQL實戰45講》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章