MySQL面試問題

索引是什麼?有什麼作用以及缺點

定義:索引是存儲引擎用於快速查找數據的一種數據結構。

MySQL數據庫基本的索引類型:普通索引、唯一索引、主鍵索引和全文索引。

普通索引:允許被索引的數據列包含重複的列

唯一索引:不允許被索引的數據包含重複的列

主鍵索引:在一張表中只能定義一個主鍵索引,主鍵索引用於唯一標識一條記錄(主鍵索引必然屬於唯一索引),使用關鍵字PRIMARY KEY創建

索引的目的是什麼

  • 快速訪問數據表中的特定信息,提高檢索速度
  • 創建唯一性索引,保證數據庫表中每一行數據的唯一性
  • 加速表和表之間的連接
  • 使用分組和排序子句進行數據檢索時,可以顯著減少查詢中分組和排序時間

索引對數據庫系統的負面影響

  • 創建和維護索引需要耗費時間。這個時間隨着數據量增加而增加
  • 索引需要佔用額外的物理空間。
  • 對錶進行增、刪、改的時候需要動態維護,降低了數據的維護速度。

建立索引的原則

  • 頻繁使用的字段
  • 選擇性高的字段
  • 需要排序的字段

主鍵、外鍵和索引的區別

主鍵:唯一標識一條記錄,不能有重複,不允許爲空。一個表只能有一個主鍵

外鍵:表的外鍵是另一個表的主鍵,外鍵可以有重複的,可是爲空值。一個表可以有多個外鍵

索引:用來提高查詢排序的速度,沒有重複值,但允許有一個空值。一個表可以有多個唯一索引。

MySQL底層實現,MySQL有什麼引擎

MySQL底層採用B+樹實現,B+樹可以看作2-3樹的一種擴展,B+樹是每個節點允許存在多個元素,並且每個節點有多個孩子的多叉查找樹,B+樹的非葉子節點存儲的是導航信息,不包含實際的值,而葉子節點存儲了實際的值,所有的葉子節點和相鄰的節點採用鏈表連接,便於區間查找和遍歷。

關於葉子節點存儲的值,在InnoDB中非主鍵索引中,存儲的是主鍵的信息,而聚簇索引(主鍵索引)中存儲的是實際數據。而在MyISAM中葉子節點存儲的是指向實際數據存儲位置的指針。MySQL在5.5版本採用的是MyISAM作爲默認的數據庫引擎,之後就被更優秀的InnoDB引擎替代。

InnoDB和MyISAM區別,InnoDB替代了MyISAM,那麼MyISAM是否一無是處。

MyISAM支持全文索引,不支持事務,不支持外鍵,只支持表級鎖,不支持行級鎖。

InnoDB支持事務,支持全文索引,支持外鍵,支持行級鎖。

採用MyISAM(可被壓縮,需要的存儲空間較小)的場景:

  1. 讀多寫少,R/W>100:1
  2. 併發不高
  3. 表數據量小

什麼是事務,事務特性

事務指的是滿足ACID特性的一組操作。

Atomicity 原子性:事務被視爲不可分割的最小單元,要麼全部提交成功,要麼全部失敗回滾。

Consistency 一致性:數據庫在事務執行前後保持一致的狀態。

Isolation 隔離性:一個事務所做的修改在最終提交之前,對其他事務是不可見的。

Durability 持久性:一旦事務提交,則其修改將會被永久保存到數據庫中。

如何設計一個高併發的系統

  1. 數據庫的優化,包括合理的事務隔離級別、SQL語句優化、索引優化
  2. 使用緩存,儘量減少數據庫IO
  3. 分佈式數據庫、分佈式緩存
  4. 服務器的負載均衡

鎖的優化策略

  1. 讀寫分離
  2. 分段加鎖
  3. 減少鎖持有的時間
  4. 多個線程儘量以相同的順序去獲取資源

優化SQL的方法

MySQL數據庫優化的八種方式(經典必看)

  • 選取最適用的字段屬性,儘可能減少定義字段寬度,儘量把字段設置NOTNULL,例如’省份’、'性別’最好適用ENUM

  • 使用連接(JOIN)來代替子查詢

  • 適用聯合(UNION)來代替手動創建的臨時表

  • 事務處理

  • 鎖定表、優化事務處理

  • 適用外鍵,優化鎖定表

  • 建立索引

如何進行SQL優化

1. 選擇正確的存儲引擎

以 MySQL爲例,包括有兩個存儲引擎 MyISAM 和 InnoDB,每個引擎都有利有弊。

MyISAM 適合於一些需要大量查詢的應用,但其對於有大量寫操作並不是很好。甚至你只是需要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都無法操作直到讀操作完成。另外,MyISAM 對於 SELECT COUNT(*) 這類的計算是超快無比的。

InnoDB 的趨勢會是一個非常複雜的存儲引擎,對於一些小的應用,它會比 MyISAM 還慢。但是它支持行級鎖 ,於是在寫操作比較多的時候,會更優秀。並且,他還支持更多的高級應用,比如:事務、外鍵等。

2. 優化字段的數據類型

記住一個原則,越小的列會越快。如果一個表只會有幾列罷了(比如說字典表,配置表),那麼,我們就沒有理由使用 INT 來做主鍵,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 會更經濟一些。

如果你不需要記錄時間,使用 DATE 要比 DATETIME 好得多。當然,你也需要留夠足夠的擴展空間。

3. 爲搜索字段添加索引

索引並不一定就是給主鍵或是唯一的字段。如果在你的表中,有某個字段你總要會經常用來做搜索,那麼最好是爲其建立索引,除非你要搜索的字段是大的文本字段,那應該建立全文索引。

4. 避免使用SELECT * 從數據庫中讀取多餘的信息

避免使用Select 從數據庫裏讀出越多的數據,那麼查詢就會變得越慢。

並且,如果你的數據庫服務器和WEB服務器是兩臺獨立的服務器的話,這還會增加網絡傳輸的負載。

即使你要查詢數據表的所有字段,也儘量不要用*通配符,善用內置提供的字段排除定義也許能給帶來更多的便利。

5. 使用ENUM而不是VARCHAR

ENUM 類型是非常快和緊湊的。在實際上,其保存的是 TINYINT,但其外表上顯示爲字符串。

這樣一來,用這個字段來做一些選項列表變得相當的完美。

例如,性別、民族、部門和狀態之類的這些字段的取值是有限而且固定的,那麼,你應該使用 ENUM 而不是 VARCHAR。

6. 儘可能使用NOT NULL

NULL值需要額外的空間,並且,在你進行比較的時候,你的程序會更復雜。

除非你有一個很特別的原因去使用 NULL 值,你應該總是讓你的字段保持 NOT NULL。

當然,並不是說就不能使用NULL值了,現實情況是很複雜的,依然會有些情況下,你需要使用NULL值。

7. 固定長度的表會提高性能

如果表中所有字段都是固定長度的,整個表都會被認爲是static的。固定長度的表會提高性能,因爲這些字段固定後,MySQL很容易計算下一行數據的偏移量,讀取速度自然會變快。另外固定長度的表也很容易被緩存和重建。

唯一的副作用是固定長度的字段會浪費一些空間。另外表中一旦有了VARCHAR、TEXT、BLOB這些類型字段之一,就不再是固定長度靜態表了。

什麼是存儲過程?有哪些優缺點

存儲過程是一組爲了完成特定功能的SQL語句集合,經編譯後存儲在數據庫中,用戶通過指定存儲過程的名稱並給出參數(如果該存儲過程帶有參數)來執行它。

1.存儲過程只在創造時進行編譯,以後每次執行存儲過程都不需再重新編譯,而一般SQL 語句每執行一次就編譯一次,所以使用存儲過程可提高數據庫執行速度。
2.當對數據庫進行復雜操作時(如對多個表進行Update,Insert,Query,Delete 時),可將此複雜操作用存儲過程封裝起來與數據庫提供的事務處理結合一起使用。
3.存儲過程可以重複使用,可減少數據庫開發人員的工作量
4.安全性高,可設定只有某此用戶才具有對指定存儲過程的使用權

相對於直接使用SQL 語句,在應用程序中直接調用存儲過程有以下好處
(1)減少網絡通信量。
調用一個行數不多的存儲過程與直接調用SQL 語句的網絡通信量可能不會有很大的差別,可是如果存儲過程包含上百行SQL 語句,那麼其性能絕對比一條一條的調用SQL 語句要高得多。
(2)執行速度更快。
有兩個原因:首先,在存儲過程創建的時候,數據庫已經對其進行了一次解析和優化。其次,存儲過程一旦執行,在內存中就會保留一份這個存儲過程,這樣下次再執行同樣的存儲過程時,可以從內存中直接調用。
(3)更強的適應性。
由於存儲過程對數據庫的訪問是通過存儲過程來進行的,因此數據庫開發人員可以在不改動存儲過程接口的情況下對數據庫進行任何改動,而這些改動不會對應用程序造成影響。
(4) 分佈式工作。
應用程序和數據庫的編碼工作可以分別獨立進行,而不會相互壓制。

缺點:
1.如果更改範圍大到需要對輸入存儲過程的參數進行更改,或者要更改由其返回的數據,則您仍需要更新程序集中的代碼以添加參數、更新 GetValue() 調用,等等,這時候估計比較繁瑣了。
2.可移植性差。由於存儲過程將應用程序綁定到 SQL Server,因此使用存儲過程封裝業務邏輯將限制應用程序的可移植性。

談談三大範式,什麼時候使用反範式設計

三大範式

  1. 第一範式:!NF要求字段屬性具有原子性,不可再分解。是對屬性的原子性約束。
  2. 第二範式:2NF要求非主屬性完全函數依賴於鍵碼。是對記錄的唯一性約束,要求記錄有唯一標識。
  3. 第三範式:3NF要求非主屬性不傳遞函數依賴於鍵碼。是對字段冗餘性的約束,即任何字段不能由其他字段派生出來。

範式化設計的優缺點

優點:減少數據冗餘,使得更新速度快,表格體積小

缺點:對於查詢需要多個表進行關聯的情況,降低了查詢效率,難以進行索引優化。

反範式化設計

優點:可以減少表的關聯,更好地進行索引優化

缺點:數據冗餘以及數據異常,數據的修改需要更多的成本。

什麼是視圖,以及視圖的使用場景

視圖是一種虛擬的表,具有和物理表相同的功能。

可以對視圖進行增,改,查操作。視圖通常是有一個表或者多個表的行或列的子集。

對視圖的修改不影響基本表。相比多表查詢,它使得我們獲取數據更容易。

MySQL鎖總結

MySQL鎖總結

InnoDB意向鎖詳解

drop、delete和truncate的區別及使用場景

相同點:

drop、delete、truncate都是刪除表的內容

不同點:

  • delete:刪除表的內容,表的結構還存在,不釋放空間,可以回滾恢復。
  • drop:刪除內容和結構,釋放空間,沒有備份表之前要慎用。
  • truncate:刪除表的內容,表的結構還在,可以釋放空間,沒有備份表之前要慎用。

解釋MySQL外連接、內連接的區別

內聯接:僅顯示兩個聯接表中的匹配行的聯接

左外聯接:包括第一個命名錶(“左表”,出現在JOIN子句的最左邊)中的所有行。不包括右表中的不匹配行。

右外聯接:包括右表中的所有行。不包括左表中的不匹配行。

對於大流量的網站,您採用什麼樣的方法來解決各頁面訪問量統計問題?

對於當今大流量的網站,每天幾千萬甚至上億的流量,是如何解決訪問量問題的呢?以下是一些總結的方法:
第一,確認服務器硬件是否足夠支持當前的流量。
普通的P4服務器一般最多能支持每天10萬獨立IP,如果訪問量比這個還要大,那麼必須首先配置一臺更高性能的專用服務器才能解決問題,否則怎麼優化都不可能徹底解決性能問題。

第二,優化數據庫訪問。
服務器的負載過大,一個重要的原因是CPU負荷過大,降低服務器CPU的負荷,才能夠有效打破瓶頸。而使用靜態頁面可以使得CPU的負荷最小化。前臺實現完全的靜態化當然最好,可以完全不用訪問數據庫,不過對於頻繁更新的網站,靜態化往往不能滿足某些功能。
緩存技術就是另一個解決方案,就是將動態數據存儲到緩存文件中,動態網頁直接調用這些文件,而不必再訪問數據庫,WordPress和Z-Blog都大量使用這種緩存技術。
如果確實無法避免對數據庫的訪問,那麼可以嘗試優化數據庫的查詢SQL.避免使用Select *from這樣的語句,每次查詢只返回自己需要的結果,避免短時間內的大量SQL查詢。

第三,禁止外部的盜鏈。
外部網站的圖片或者文件盜鏈往往會帶來大量的負載壓力,因此應該嚴格限制外部對於自身的圖片或者文件盜鏈,好在目前可以簡單地通過refer來控制盜鏈,Apache自己就可以通過配置來禁止盜鏈,IIS也有一些第三方的ISAPI可以實現同樣的功能。當然,僞造refer也可以通過代碼來實現盜鏈,不過目前蓄意僞造refer盜鏈的還不多,可以先不去考慮,或者使用非技術手段來解決,比如在圖片上增加水印。

第四,控制大文件的下載。
大文件的下載會佔用很大的流量,並且對於非SCSI硬盤來說,大量文件下載會消耗CPU,使得網站響應能力下降。因此,儘量不要提供超過2M的大文件下載,如果需要提供,建議將大文件放在另外一臺服務器上。目前有不少免費的Web2.0網站提供圖片分享和文件分享功能,因此可以儘量將圖片和文件上傳到這些分享網站。

第五,使用不同主機分流主要流量
將文件放在不同的主機上,提供不同的鏡像供用戶下載。比如如果覺得RSS文件佔用流量大,那麼使用FeedBurner或者FeedSky等服務將RSS輸出放在其他主機上,這樣別人訪問的流量壓力就大多集中在FeedBurner的主機上,RSS就不佔用太多資源了。

第六,使用流量分析統計軟件。
在網站上安裝一個流量分析統計軟件,可以即時知道哪些地方耗費了大量流量,哪些頁面需要再進行優化,因此,解決流量問題還需要進行精確的統計分析纔可以。我推薦使用的流量分析統計軟件是GoogleAnalytics(Google分析)。

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