背景
近期為了保障線上資料庫的穩定性,我決定針對一些大表的歷史資料有計劃地進行備份遷移,但是呢,發現一個奇特的現象,Navicat統計行數和表自身count統計數竟然不一致!?0.0
Navicat
Navicat作為資料庫管理工具,在業界廣受歡迎,先甭管你電腦上現在正在執行的Navicat是正版還是盜版(你不說我也知道),不可否認的是,在我從事17年從事後端開發以來,嘗試了很多同類工具,Navicat在功能上完全碾壓其他資料庫管理工具,尤其是細節方面,在這裡不一一列舉了,總之一個字,就是很好用(不接受反駁,除非你說出來一個讓我心服口服的工具)。
整個經過
這次大表遷移備份,我的整體思路是:首先用Navicat對庫內所有的表按照行數降序排序,然後選取Top10進行遷移備份。但是一如既往細心的我發現,它介面的統計行數竟然和我自己count這張錶行數不一致?!難道要顛覆我對Navicat的認可嘛。
select count(1) from big_table_name;
為什麼呢?
這讓我很是詫異,一度以為自己出現了幻覺,再三確認自己沒有帶VR眼鏡後,我踏上了尋找答案的征程。我開始思考,Mysql作為一個資料庫,自身肯定就有各個表的統計,而Navicat只是作為一個視覺化介面,讓資料肉眼可見。
Navicat:這鍋我可不背。
為了證實我的猜想,我查閱了官方文件及其他相關資料,果然,MySQL 在 information_schema.TABLES
表中息存放了所有表的資訊。
select * from information_schema.TABLES;
檢視了這張表以後,發現表裡統計記錄TABLE_ROWS
欄位的確實與事實count不符……
這又是為什麼呢?
我又陷入了沉思,帶著疑惑,繼續翻閱著文件,突然,看到MySQL官方文件對TABLE_ROWS
的解釋:
The number of rows. Some storage engines, such as MyISAM, store the exact count. For other storage engines, such as InnoDB, this value is an approximation, and may vary from the actual value by as much as 40% to 50%. In such cases, use SELECT COUNT(*) to obtain an accurate count.
看了這段話我頓悟啦,你是不是也明白怎麼回事啦。什麼?你沒看太明白?好吧,沒關係,你可能需要通過翻譯軟體的直譯+理解,才懂得其中真正的含義。原來,TABLE_ROWS
這個欄位不同儲存引擎的計數規則不一致,比如MyISAM引擎這表儲存TABLE_ROWS
儲存的就是精確的行數,而對於其他的儲存引擎,比如 InnoDB,這個值只是一個近似值,與實際值相差40%-50%左右。所以,在這種情況下,我們想要得到一個準確的計數,只能使用 SELECT COUNT(*) 來獲得。
那又如何修正呢?
雖然疑惑得到了解答。但,和我一樣有強迫症的朋友肯定會問,如何修正這個值呢?真是知道越多,未知越多,網上說可以通過
Analyze table big_table_name
得以更正這個資料,但是我動手執行之後發現,並不能更正資料,且該操作不僅耗時還會鎖表,並不推薦使用……說到這,我的強迫症竟然不治自愈了。
朋友,你有更好的辦法嘛?歡迎留言。
請關注微信公眾號:程式設計師小明!!!
本文可轉載,但需宣告原文出處。 程式設計師小明,一個很少加班的程式設計師。歡迎關注微信公眾號“程式設計師小明”,獲取更多優質文章。