天天看點

為什麼明明表資料删掉一半,表檔案大小不變?

1)表結構和表資料是怎樣放置的?

  • 8.0之前啊,表結構是放在.frm為字尾的檔案中。8.0之後呢,可以放在了系統資料表中。

2)先來 看看參數innodb_file_per_table的含義是怎麼?

  • 當值為off的時候,表示我的檔案資料是放在共享表中的。
  • 當值為on的時候,那檔案資料就是單獨放在一個檔案中的,每個資料表都有一個對應的檔案。
  • 從mysql5.6.6開始,預設值 就是on了。

3)資料的删除流程是怎樣的?

為什麼明明表資料删掉一半,表檔案大小不變?
  • 假如要 删R4這一行資料 ,僅僅是打個标記,代表 删除了 ,是邏輯上的删除,并不會實際的把這部分位址空間移除。那以後要插入新的資料的話還得看滿足範圍不。
  • 那如果是删除整頁的話,那就是标記整個頁都是被删除的了,你要插什麼範圍的資料進來都是可以的。

4)頁合并的過程中還發生了什麼?

  • 如果兩個頁的使用率都很低,那資料合并到其中一頁之後,剩下的一頁就被标記為可複用狀态。

5)如果我們用delete指令删除整個表資料,會發生什麼?

  • 标記一下所有的資料頁上的資料都被删除了,大家想用的話就用。僅僅是邏輯上的删除。但是磁盤上的檔案還是實實在在存在的。

6)delete删除的時候,是标記 我們的資料頁為可複用狀态,但是實際上我們有一些記憶體是利用不到的,這個就是記憶體碎片,在随機插入的時候也會造成記憶體碎片,那如何去解決記憶體碎片這個問題呢?

  • 用alter table 表名 engine = innoDB指令重建表
  • 5.5之前,是把A表的東一行西一行的資料整齊的碼放到一個臨時表,臨時表中資料是挨着的,然後用這張臨時表 來替換A表。這種方式的話需要停擺我們的業務 ,因為重建過程中如果有新的資料到A上,那到不了臨時表上,會造成資料丢失 。
  • 5.6之後,優化了我們重建表的細節 ,A表的資料生成一顆B+樹,然後資料整齊碼放到一個臨時檔案(注意這裡不再表是檔案)的時候,如果有新的業務插進來資料,我把這些資料記錄到一個日志上row log,然後等我把資料碼放到我們的臨時檔案上後,再把日志中的資料添加到臨時檔案。最後臨時檔案和A表 交換。