來了,朋友們,追命連環問系列之MySQL部分開始了。準備好了嗎?本次連環問主要設計以下四個方面:
-
MySQL執行流程
-
MySQL存儲引擎
-
表字段如何設計
-
查詢緩存
一,MySQL的執行流程
面試官:你知道一條sql語句進來的流程是什麼嗎?
我:知道,我來說一下。MySQL的架構是由兩部分組成的:server層和存儲引擎層。
Server層:主要包括連接器、查詢緩存、分析器、優化器、執行器等,所有跨存儲引擎的功能都在這一層實現,比如存儲過程、觸發器、視圖,函數等,還有一個通用的日誌模塊 binglog日誌模塊。
存儲引擎:主要負責數據的存儲和讀取,採用可以替換的插件式架構,支持InnoDB、MyISAM、Memory等多個存儲引擎,其中InnoDB引擎有自有的日誌模塊redolog 模塊。
InnoDB 5.5.5版本作爲默認引擎。
1.當客戶端連接到MySQL服務器時,服吧務器會對其進行認證。通過用戶名與密碼認證,也可以通過SSL證書進行認證。
登錄認證後,服務器還會驗證客戶端是否有執行某個查詢的操作權限。權限在連接的時候就確定了(分爲長連接和短連接),如果該用戶要變更權限需要重新連接,連接後長時間沒有動作則會自動斷開。
2.在正式查詢之前,服務器會檢查查詢緩存,如果能找到對應的查詢,則不必進行查詢分析,優化,執行等過程,直接返回緩存中的結果。
3.MySQL的分析器主要用來進行詞法分析和語法分析。詞法分析根據關鍵字分析語句,語法分析根據MySQL語法分析語句是否正確。
4.查詢優化器將解析樹轉化爲查詢計劃,優化器是在表裏面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的連接順序。優化器就是根據成本找到這其中最優的執行計劃。
5.優化器之後就開始進入到執行器,執行計劃調用查詢執行引擎,而查詢引擎通過一系列API接口查詢到數據。
6.得到數據之後,在返回給客戶端的同時,同時會將數據存在查詢緩存中,增加下次查詢的速度。
二,MySQL的存儲引擎
面試官:那你知道MySQL的存儲引擎都有哪些嗎?
答:MySQL主要有InnoDB,MyISAM,MEMORY,MERGE和ARCHIVE。
Mysql在5.5版本之後默認存儲引擎是InnoDb,而再次之前MyISAM是默認的存儲引擎。
面試官:那你能說說MyISAM和InnoDB之間的區別嗎?
1、MYISAM不支持外鍵和事務,而InnoDB支持。MyISAM支持全文類型索引,而InnoDB不支持全文索引。
2、InnoDB爲行級鎖,MyISAM爲表級鎖,所以InnoDB相對於MyISAM來說,更容易發生死鎖,鎖衝突的概率更大,而且上鎖的開銷也更大,因爲需要爲每一行加鎖;由於鎖粒度的不同,InnoDB比MyISAM支持更高的併發;
3、在備份容災上,InnoDB支持在線熱備,有很成熟的在線熱備解決方案;
4、查詢性能上,MyISAM的查詢效率高於InnoDB,因爲InnoDB在查詢過程中,是需要維護數據緩存,而且查詢過程是先定位到行所在的數據塊,然後在從數據塊中定位到要查找的行;而MyISAM可以直接定位到數據所在的內存地址,可以直接找到數據;
5、SELECT COUNT(*)語句,如果行數在千萬級別以上,MyISAM可以快速查出,而InnoDB查詢的特別慢,因爲MyISAM將行數單獨存儲了(計數器),而InnoDB需要逐行去統計行數;
所以如果使用InnoDB,而且需要查詢行數,則需要對行數進行特殊處理,如:離線查詢並緩存;
6、MyISAM的表結構文件包括:.frm(表結構定義),.MYI(索引),.MYD(數據);而InnoDB的表數據文件爲:.ibd和.frm(表結構定義);
7、MyISAM刪除數據時會產生碎片空間(佔用表文件空間),需要定期通過optimizetable table-name手動優化。而Innodb不會。
這些不同也導致了他們應用場景的不同:
-
MyISAM管理非事務表。它提供高速存儲和檢索,以及全文搜索能力。如果應用中需要執行大量的SELECT查詢,那麼MyISAM是更好的選擇。
-
InnoDB用於事務處理應用程序,具有衆多特性,包括ACID事務支持。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多用戶併發操作的性能。
三,表字段的設計
面試官:嗯回答的很不錯,那你平常開發中表字段是怎麼設計的呢?
我:首先表名和字段名要規範,使用下劃線進行連接。
字段設計原則:
1,儘量使用not null ,並且賦予初始值,建議 default ‘’,給一個空串,空串不佔內存空間,NULL是佔內存空間的,nuI數值的計算邏輯比較複雜。
2,char爲定長(超過長度的內容將被截掉), varchar爲非定長,text對內容 長度的保存額外保存而varchar對長度的保存佔用數據空間。
對於varchar(N)只需要分配真正需要的空間,更大的定義列會消耗更多的內存,在使用內存臨時表進行排序或操作時會根據定義的長度進行內存分配。
3,對數字的精度要有要求,對較長的數字數據可以使用decimal。
4,字段數不要過多字段註釋是必要的、字段命名見名思意、可以預留字段以備擴展。
同時要儘量滿足三大範式:
①. 第一範式:對屬性的原子性(關係型數據庫有列的念,默認就符合了)
②. 第二範式:對記錄的唯一性,要求記錄有唯一標識。需要確保數據庫表中的每一列都和主鍵相關,而不能只與主鍵的某一部分相關(主要針對聯合主鍵而言)
③. 第三範式:對字段的冗餘性。消除對主鍵的傳遞依賴;需要確保數據表中的每一列數據都和主鍵直接相關,而不能間接相關。如商品表可分爲商品簡略信息表和商品詳情表兩張表。
四,查詢緩存
面試官:看來你平常表的設計應該不錯了,那你知道MySQL的查詢緩存嗎?
我:知道的。查詢緩存就是將select的查詢結果緩存起來,key爲sql語句,value爲查詢結果。如果SQL功能一樣,但只是多個空格或略微改動都會導致key的不匹配。
查詢緩存需要客戶端開啓,設置query. cache. _type。
0-不開啓
1-開啓表示始終緩存,默認緩存每條select,針對某個sq不緩存: select sql-no-cache
2-開啓表示按需緩存,默認都不緩存,通過select sql-cache制定緩存哪-個條
面試官:那你遇到慢查詢都是怎麼優化的呢?
我:首先,我會去查看慢查詢的日誌,定位到哪條語句出現了慢查詢。然後再定位到相應的表和代碼塊。根據業務進行優化。
有可能是以下幾種情況:
1,沒有創建索引,或索引沒起作用。
2,數據庫表結構設計不合理。
3,分解關聯查詢,將一個大的查詢分解爲多個小的查詢。
4,優化Limit分頁。比如偏移量太大。
好啦,今天的追命連環問就到這裏了,下次繼續,如對文章有疑惑或補充的地方歡迎留言交流(●'◡'●)。
相關推薦閱讀