MySQL筆記(實踐篇)

普通索引和唯一索引,應該怎麼選擇?

select id from T where k=5

查詢過程(差別不大)

通過普通索引的查詢過程:查找到k=5記錄,接着查找下一條記錄直到不滿足條件

通過唯一索引的查詢過程:查找到k=5記錄後直接返回

由於查詢過程是把整個數據頁(默認16kb)讀入內存,普通索引會多一次指針尋找和計算,如果剛好記錄在數據頁最後,則要多讀取一個數據頁,而這影響微乎其微

更新過程(寫多讀少的表建議使用普通索引)

通過普通索引的更新過程:當數據在內存中則直接更新;如果不在內存中,則將更新寫入change buffer(在從數據庫讀取數據後,會執行meige操作,將change buffer的更新作用到數據上,這樣才能得到一致的數據)

通過唯一索引的更新過程:當數據在內存中則直接更新;如果不在內存中,由於要判斷數據是否唯一,也需要將數據頁讀入內存中,既然數據頁都讀入內存中了,直接更新就好,不需要使用change buffer

change buffer減少了隨機磁盤訪問,性能提升明顯

對於寫多讀少的系統,更新寫入change buffer不會立即觸發merge,對性能提升

對於寫少讀多的系統,更新寫入change buffer後馬上及觸發merge,反而影響性能

注意redo log 和 change buffer的區別

redo log減少隨機寫磁盤的操作(WAL,先寫日誌有空再寫入磁盤)

change buffer減少隨機讀磁盤的操作(更新的時候不讀數據)


MySQL爲什麼有時候會選錯索引?

索引上不同的值越多,區分度就越大

當MySQL選錯索引時,可以用force index(索引名)強制使用索引

由於索引統計信息不準確導致的問題,可以用 analyze table 來解決


怎麼給字符串字段加索引?

完整索引

如果字段較長的話,比較佔空間

前綴索引

節省空間

增加掃描次數且無法使用覆蓋索引(每次都要回表判斷條件是否符合)

倒序存儲

對於身份證這種前綴區分度不夠的字段,可以使用倒序取後6位的方式設置索引,查詢時使用如下語句


select field_list from t where id_card = reverse('input_id_card_string');

不支持範圍查詢、額外CPU消耗(reverse函數)

hash字段

額外增加一個hash字段作爲索引

不支持範圍查詢


爲什麼我的MySQL會“抖”一下?

當內存數據頁跟磁盤數據頁內容不一致的時候,我們稱這個內存頁爲“髒頁”。

內存數據寫入到磁盤後,內存和磁盤上的數據頁的內容就一致了,稱爲“乾淨頁”。

平時執行很快的更新操作,其實就是在寫內存和日誌,而 MySQL 偶爾“抖”一下的那個瞬間,可能就是在刷髒頁(flush)

以下幾種情況刷髒頁

  • redo log寫滿了
  • 內存不足
  • 系統空閒時
  • MySQL正常關閉

通過innodb_io_capacity控制innodb刷髒頁的速度

innode_flush_neighbors參數,控制刷髒頁時是否把鄰近的髒頁也順便一起刷了(1是,0否),8.0版本中默認0

如果是固態硬盤,建議設置爲0


 

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