??大家好,我是陳哈哈,北漂五年,相信大家和我一樣,
都有一個大廠夢,作為一名資深Java選手,深知面試重要性,接下來我準備用100天時間,基于Java崗面試中的高頻面試題,以每日3題的形式,帶你過一遍熱門面試題及恰如其分的解答,
??一路走來,隨著問題加深,發現不會的也愈來愈多,但底氣著實足了不少,相信不少朋友和我一樣,榷訓月累才是最有效的學習方式!想起高三時一個同學的座右銘:只有沉下去,才能浮上來,共勉(juan),

工地坐標:上海某寫字樓
作者:maybe
車票
- 面試題1:有個需求需要快速洗掉MySQL表中一億條資料,表中有2億資料,能說一下你的思路么?
- 面試題2:剛才你提到了邏輯洗掉,你是怎么看邏輯洗掉和物理洗掉的?
- 面試題3:大型專案中,mysql的主鍵需要全域唯一怎么辦?
- 每日小結
??本欄目Java開發崗高頻面試題主要出自以下各技術堆疊:Java基礎知識、集合容器、并發編程、JVM、Spring全家桶、MyBatis等ORMapping框架、MySQL資料庫、Redis快取、RabbitMQ訊息佇列、Linux操作技巧等,
面試題1:有個需求需要快速洗掉MySQL表中一億條資料,表中有2億資料,能說一下你的思路么?
??我們知道MySQL洗掉資料的方式有多種比如DELETE、TRUNCATE、DROP等,都屬于物理洗掉,但在實際場景中,很多時候是不能直接用的,
??比如咱們說的這張表中有2億條資料,要刪其中1億條,以InnoDB引擎為例,直接加WHERE條件DELETE是不現實的,因為DELETE是一條一條刪,要把操作記錄到binlog日志(前提開啟了binlog),洗掉少量資料還可以,洗掉1億潭訓非常慢,并且不會釋放出磁盤空間,還得用optimize或repair來壓縮資料表來釋放硬碟空間,如果欄位內容多,IO成本很高,CPU各種過高,耗時更長,不可行,
??如果我用truncate刪資料,速度倒是很快,能直接釋放磁盤空間,但這是全表資料洗掉,直接清空資料檔案或磁區磁盤空間,剩下不用刪的1億條又怎么辦呢?
??因此我們要根據實際情況入手,比如表中有2億條資料,要刪其中1億條;
-
方法一:著急的話,可以臨時使用邏輯洗掉,選一個欄位或加一個欄位如is_deleted,作為邏輯洗掉標志,然后通過該欄位過濾后繼續處理資料,等到夜深人靜,,, -
方法二:可以新建一張表結構一致的表,把不用洗掉的資料導進去,然后drop原表,再把新表名稱改為原表名稱;這是一種比較常見的方式,要注意的是,如果索引較多或索引欄位較大的話,記得先導資料,再加索引,別問我為什么,
我們簡單看一下方法二的操作流程:
1、復制表+洗掉索引
create table new_T like T;
ALTER TABLE new_T DROP INDEX index_name1;
ALTER TABLE new_T DROP INDEX index_name2;
2、插入資料要分批插入,建議為10w-50w一次,根據你的MySQL服務器性能來定,可以按ID查詢后插入,也可以null as id按新順序插入,如:
insert into new_T (select null as id,col1,col2,col3 from T where id>500000 and id<=600000);
insert into new_T (select null as id,col1,col2,col3 from T where id>600000 and id<=700000);
...
3、drop洗掉掉老表
drop table T;
4、重命名新表為new_T
alter table new_T rename to T;

課間休息,又來秀一下來自咱們群里同學的搬磚工地,坐標:??,
作者:if you
面試題2:剛才你提到了邏輯洗掉,你是怎么看邏輯洗掉和物理洗掉的?
??我理解物理洗掉指的將資料從磁盤中真實洗掉,而邏輯洗掉則是在代碼層面的,多是將洗掉資料行的is_deleted欄位置成1,后續只操作is_deleted=0的那些未被洗掉的資料,
??在嚴謹的開發環境中,實際上是沒有洗掉這一說的,訂單作廢,用戶禁用,優惠券作廢都是狀態的變化,而不應該讓資料從磁盤消失,所以 SQL 里面 DELETE 在真實生產環境里都不應該出現,除DBA賬號外的其他用戶不應有DELETE、TRUNCATE、DROP權限,而只有UPDATE權限,
??我還見過有單位將MySQL的update命令封裝成洗掉命令的~~然后用戶只能看到表中或視圖中is_deleted=0的資料,好像是實作了權限隔離,其實就是閑的慌,
??當然了,邏輯洗掉其實也是有問題的,邏輯洗掉的設計還會導致常用的unique key 失效;臟資料量大的時候研發人員可能會發現表中明明資料不多,但檢索速度很慢,可能會誤導研發人員的維護作業,

課間休息,來看一下來自咱們群里同學旅游拍攝的,坐標:日本,
作者:胡巴
面試題3:大型專案中,mysql的主鍵需要全域唯一怎么辦?
??在只使用單資料庫時,使用自增主鍵ID無疑是最適合的,但在集群、主從架構上時就會有一些問題,比如怎么做到主鍵的全域唯一,
使用UUID
??這時我們首先想到的解決方法可能是以UUID為主鍵,對于InnoDB這種聚集主鍵型別的引擎來說,資料會按照主鍵進行排序,由于UUID的無序性,InnoDB會產生巨大的IO壓力,此時不適合使用UUID做物理主鍵,但可以把它作為邏輯主鍵,物理主鍵依然使用自增ID,
??另外,innodb會對主鍵進行物理排序,這對auto_increment_int是個好訊息,因為后一次插入的主鍵位置總是在最后,但是對uuid來 說,這卻是個壞訊息,因為uuid是雜亂無章的,每次插入的主鍵位置是不確定的,可能在開頭,也可能在中間,在進行主鍵物理排序的時候,勢必會出現大量 IO操作影響效率,
使用自增ID
方法一:比如4臺資料庫,第一臺mysql主鍵從1開始每次加4,第二臺從2開始每次加4,以此類推,這里的4代表資料庫總量,我們叫它步長,從而保證主鍵的全域唯一,我們需要保證的就是確保自增 ID 起始點(auto_increment_offset)以及 ID 自增步長(auto_increment_increment)的正確性即可,
修改MySQL默認自動增長的步長
-- 設定序列的增長值
set global auto_increment_increment=1;
方法二:通過集群編號加集群內的自增(auto_increment型別)兩個欄位共同組成唯一主鍵,優點是實作簡單,維護也比較簡單,對應用透明,缺點是參考關聯操作相對比較復雜,需要兩個欄位,主鍵占用空間較大,在使用 InnoDB 的時候這一點的副作用很明顯(但是這方式僅僅多了一個smallint兩個位元組,100W也就多2M),
每日小結
??今天我們復習了面試中常考的資料庫相關的三個實際問題,你做到心中有數了么?對了,如果你的朋友也在準備面試,請將這個系列扔給他,如果他認真對待,肯定會感謝你的!!好了,今天就到這里,學廢了的同學,記得在評論區留言:打卡,,給同學們以激勵,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/299006.html
標籤:其他
