1. 程式人生 > >【SQL】常用MySQL面試題(一)

【SQL】常用MySQL面試題(一)

1、資料庫事務的四個特性及含義

資料庫事務transanction正確執行的四個基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔離性(Isolation)、永續性(Durability)。

  • 原子性:整個事務中的所有操作,要麼全部完成,要麼全部不完成,不可能停滯在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
  • 一致性:在事務開始之前和事務結束以後,資料庫的完整性約束沒有被破壞。
  • 隔離性:隔離狀態執行事務,使它們好像是系統在給定時間內執行的唯一操作。如果有兩個事務,執行在相同的時間內,執行 相同的功能,事務的隔離性將確保每一事務在系統中認為只有該事務在使用系統。這種屬性有時稱為序列化,為了防止事務操作間的混淆,必須序列化或序列化請 求,使得在同一時間僅有一個請求用於同一資料。
  • 永續性:在事務完成以後,該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。

2、檢視的作用,檢視可以更改麼?

檢視是虛擬的表,與包含資料的表不一樣,檢視只包含使用時動態檢索資料的查詢;不包含任何列或資料。使用檢視可以簡化複雜的sql操作,隱藏具體的細節,保護資料;檢視建立後,可以使用與表相同的方式利用它們。
檢視不能被索引,也不能有關聯的觸發器或預設值,如果檢視本身內有order by 則對檢視再次order by將被覆蓋。
建立檢視:create view XXX as XXXXXXXXXXXXXX;
對於某些檢視比如未使用聯結子查詢分組聚集函式Distinct Union等,是可以對其更新的,對檢視的更新將對基表進行更新;但是檢視主要用於簡化檢索,保護資料,並不用於更新,而且大部分檢視都不可以更新。

3、drop,delete與truncate的區別

drop直接刪掉表 truncate刪除表中資料,再插入時自增長id又從1開始 delete刪除表中資料,可以加where字句。

(1) DELETE語句執行刪除的過程是每次從表中刪除一行,並且同時將該行的刪除操作作為事務記錄在日誌中儲存以便進行進行回滾操作。TRUNCATE TABLE 則一次性地從表中刪除所有的資料並不把單獨的刪除操作記錄記入日誌儲存,刪除行是不能恢復的。並且在刪除的過程中不會啟用與表有關的刪除觸發器。執行速度快。

(2) 表和索引所佔空間。當表被TRUNCATE 後,這個表和索引所佔用的空間會恢復到初始大小,而DELETE操作不會減少表或索引所佔用的空間。drop語句將表所佔用的空間全釋放掉。

(3) 一般而言,drop > truncate > delete

(4) 應用範圍。TRUNCATE 只能對TABLE;DELETE可以是table和view

(5) TRUNCATE 和DELETE只刪除資料,而DROP則刪除整個表(結構和資料)。

(6) truncate與不帶where的delete :只刪除資料,而不刪除表的結構(定義)drop語句將刪除表的結構被依賴的約束(constrain),觸發器(trigger)索引(index);依賴於該表的儲存過程/函式將被保留,但其狀態會變為:invalid。

(7) delete語句為DML(data maintain Language),這個操作會被放到 rollback segment中,事務提交後才生效。如果有相應的 tigger,執行的時候將被觸發。

(8) truncate、drop是DLL(data define language),操作立即生效,原資料不放到 rollback segment中,不能回滾

(9) 在沒有備份情況下,謹慎使用 drop 與 truncate。要刪除部分資料行採用delete且注意結合where來約束影響範圍。回滾段要足夠大。要刪除表用drop;若想保留表而將表中資料刪除,如果於事務無關,用truncate即可實現。如果和事務有關,或老師想觸發trigger,還是用delete。

(10) Truncate table 表名 速度快,而且效率高,因為:
truncate table 在功能上與不帶 WHERE 子句的 DELETE 語句相同:二者均刪除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統和事務日誌資源少。DELETE 語句每次刪除一行,並在事務日誌中為所刪除的每行記錄一項。TRUNCATE TABLE 通過釋放儲存表資料所用的資料頁來刪除資料,並且只在事務日誌中記錄頁的釋放。

(11) TRUNCATE TABLE 刪除表中的所有行,但表結構及其列、約束、索引等保持不變。新行標識所用的計數值重置為該列的種子。如果想保留標識計數值,請改用 DELETE。如果要刪除表定義及其資料,請使用 DROP TABLE 語句。

(12) 對於由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應使用不帶 WHERE 子句的 DELETE 語句。由於 TRUNCATE TABLE 不記錄在日誌中,所以它不能啟用觸發器。

4、索引的工作原理及其種類(很重要)

(可詳細參考其他文章)

5、資料庫正規化

1 第一正規化(1NF)

在任何一個關係資料庫中,第一正規化(1NF)是對關係模式的基本要求,不滿足第一正規化(1NF)的資料庫就不是關係資料庫。
所謂第一正規化(1NF)是指資料庫表的每一列都是不可分割的基本資料項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。如果出現重複的屬性,就可能需要定義一個新的實體,新的實體由重複的屬性構成,新實體與原實體之間為一對多關係。在第一正規化(1NF)中表的每一行只包含一個例項的資訊。簡而言之,第一正規化就是無重複的列

2 第二正規化(2NF)

第二正規化(2NF)是在第一正規化(1NF)的基礎上建立起來的,即滿足第二正規化(2NF)必須先滿足第一正規化(1NF)。第二正規化(2NF)要求資料庫表中的每個例項或行必須可以被惟一地區分。為實現區分通常需要為表加上一個列,以儲存各個例項的惟一標識。這個惟一屬性列被稱為主關鍵字或主鍵、主碼。
第二正規化(2NF)要求實體的屬性完全依賴於主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性,如果存在,那麼這個屬性和主關鍵字的這一部分應該分離出來形成一個新的實體,新實體與原實體之間是一對多的關係。為實現區分通常需要為表加上一個列,以儲存各個例項的惟一標識。簡而言之,第二正規化就是非主屬性非部分依賴於主關鍵字

3 第三正規化(3NF)

滿足第三正規化(3NF)必須先滿足第二正規化(2NF)。簡而言之,第三正規化(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字資訊。例如,存在一個部門資訊表,其中每個部門有部門編號(dept_id)、部門名稱、部門簡介等資訊。那麼在員工資訊表中列出部門編號後就不能再將部門名稱、部門簡介等與部門有關的資訊再加入員工資訊表中。如果不存在部門資訊表,則根據第三正規化(3NF)也應該構建它,否則就會有大量的資料冗餘。簡而言之,第三正規化就是屬性不依賴於其它非主屬性。(我的理解是消除冗餘)

6、資料庫優化的思路

1.SQL語句優化
1)應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
2)應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設定預設值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0
3)很多時候用 exists 代替 in 是一個好的選擇
4)用Where子句替換HAVING 子句 因為HAVING 只會在檢索出所有記錄之後才對結果集進行過濾

2.索引優化
看上文索引

3.資料庫結構優化
1)正規化優化: 比如消除冗餘(節省空間。。) 2)反正規化優化:比如適當加冗餘等(減少join) 3)拆分表: 分割槽將資料在物理上分隔開,不同分割槽的資料可以制定儲存在處於不同磁碟上的資料檔案裡。這樣,當對這個表進行查詢時,只需要在表分割槽中進行掃描,而不必進行全表掃描,明顯縮短了查詢時間,另外處於不同磁碟的分割槽也將對這個表的資料傳輸分散在不同的磁碟I/O,一個精心設定的分割槽可以將資料傳輸對磁碟I/O競爭均勻地分散開。對資料量大的時時表可採取此方法。可按月自動建表分割槽。
4)拆分其實又分垂直拆分和水平拆分: 案例: 簡單購物系統暫設涉及如下表: 1.產品表(資料量10w,穩定) 2.訂單表(資料量200w,且有增長趨勢) 3.使用者表 (資料量100w,且有增長趨勢) 以mysql為例講述下水平拆分和垂直拆分,mysql能容忍的數量級在百萬靜態資料可以到千萬 垂直拆分:解決問題:表與表之間的io競爭 不解決問題:單表中資料量增長出現的壓力 方案: 把產品表和使用者表放到一個server上 訂單表單獨放到一個server上 水平拆分: 解決問題:單表中資料量增長出現的壓力 不解決問題:表與表之間的io爭奪
方案: 使用者表通過性別拆分為男使用者表和女使用者表 訂單表通過已完成和完成中拆分為已完成訂單和未完成訂單 產品表 未完成訂單放一個server上 已完成訂單表盒男使用者表放一個server上 女使用者表放一個server上(女的愛購物 哈哈)

4.伺服器硬體優化
這個麼多花錢咯!

7、儲存過程與觸發器的區別

觸發器與儲存過程非常相似,觸發器也是SQL語句集,兩者唯一的區別是觸發器不能用EXECUTE語句呼叫,而是在使用者執行Transact-SQL語句時自動觸發(啟用)執行。觸發器是在一個修改了指定表中的資料時執行的儲存過程。通常通過建立觸發器來強制實現不同表中的邏輯相關資料的引用完整性和一致性。由於使用者不能繞過觸發器,所以可以用它來強制實施複雜的業務規則,以確保資料的完整性。觸發器不同於儲存過程,觸發器主要是通過事件執行觸發而被執行的,而儲存過程可以通過儲存過程名稱名字而直接呼叫。當對某一表進行諸如UPDATE、INSERT、DELETE這些操作時,SQLSERVER就會自動執行觸發器所定義的SQL語句,從而確保對資料的處理必須符合這些SQL語句所定義的規則。

8、實戰題目

一張表,裡面有ID自增主鍵,當insert了17條記錄之後,刪除了第15,16,17條記錄,再把Mysql重啟,再insert一條記錄,這條記錄的ID是18還是15 ?

答:

(1)如果表的型別是MyISAM,那麼是18。
因為MyISAM表會把自增主鍵的最大ID記錄到資料檔案裡,重啟MySQL自增主鍵的最大ID也不會丟失。
(2)如果表的型別是InnoDB,那麼是15。
InnoDB表只是把自增主鍵的最大ID記錄到記憶體中,所以重啟資料庫或者是對錶進行OPTIMIZE操作,都會導致最大ID丟失。

請簡述專案中優化sql語句執行效率的方法,從哪些方面。sql語句效能如何分析?

答:

(1)儘量選擇較小的列
(2)將where中用的比較頻繁的欄位建立索引
(3)select子句中避免使用‘*’
(4)避免在索引列上使用計算,not,in和<>等操作
(5)當只需要一行資料的時候使用limit 1
(6)保證表單資料不超過200w,適時分割表
(7)針對查詢較慢的語句,可以使用explain來分析該語句具體的執行情況