萬字長文,最常問的 MySQL 面試題集合

除了基礎題部分,本文還收集整理的 MySQL 面試題還包括如下知識點或題型:

  • MySQL 高性能索引

  • SQL 語句

  • MySQL 查詢優化

  • MySQL 高擴展高可用

  • MySQL 安全性

問題 1:char、varchar 的區別是什麼?
varchar 是變長而 char 的長度是固定的。如果你的內容是固定大小的,你會得到更好的性能。

問題 2: TRUNCATE 和 DELETE 的區別是什麼?
DELETE 命令從一個表中刪除某一行,或多行,TRUNCATE 命令永久地從表中刪除每一行。

問題 3:什麼是觸發器,MySQL 中都有哪些觸發器?
觸發器是指一段代碼,當觸發某個事件時,自動執行這些代碼。在 MySQL 數據庫中有如下六種觸發器:

問題 4:FLOAT 和 DOUBLE 的區別是什麼?

問題 5:如何在 MySQL 種獲取當前日期?

SELECT CURRENT_DATE();

問題 6:如何查詢第 n 高的工資?

SELECT DISTINCT(salary) from employee ORDER BY salary DESC LIMIT n-1,1

(提示:代碼可以左右滑動)

問題 7:請寫出下面 MySQL 數據類型表達的意義(int(0)、char(16)、varchar(16)、datetime、text)

知識點分析

此題考察的是 MySQL 數據類型。MySQL 數據類型屬於 MySQL 數據庫基礎,由此延伸出的知識點還包括如下內容:

數據類型考點:

使用策略:
對於經常變更的數據來說,CHAR 比 VARCHAR 更好,因爲 CHAR 不容易產生碎片。
對於非常短的列,CHAR 比 VARCHAR 在存儲空間上更有效率。
使用時要注意只分配需要的空間,更長的列排序時會消耗更多內存。
儘量避免使用 TEXT/BLOB 類型,查詢時會使用臨時表,導致嚴重的性能開銷。

答:int(0) 表示數據是 INT 類型,長度是 0、char(16) 表示固定長度字符串,長度爲 16、varchar(16) 表示可變長度字符串,長度爲 16、datetime 表示時間類型、text 表示字符串類型,能存儲大字符串,最多存儲 65535 字節數據)

MySQL 基礎操作:

常見操作

MySQL 的連接和關閉:mysql -u -p -h -P

-u:指定用戶名
-p:指定密碼
-h:主機
-P:端口

進入 MySQL 命令行後:G、c、q、s、h、d

G:打印結果垂直顯示
c:取消當前 MySQL 命令
q:退出 MySQL 連接
s:顯示服務器狀態
h:幫助信息
d:改變執行符

MySQL 存儲引擎:

1、InnoDB 存儲引擎,

2、MyISAM 存儲引擎,

3、其他表引擎,
Archive、Blackhole、CSV、Memory

使用策略
在大多數場景下建議使用 InnoDB 存儲引擎。

MySQL 鎖機制

表鎖是日常開發中的常見問題,因此也是面試當中最常見的考察點,當多個查詢同一時刻進行數據修改時,就會產生併發控制的問題。共享鎖和排他鎖,就是讀鎖和寫鎖。

鎖的粒度

MySQL 事務處理

存儲過程

使用策略

觸發器

提供給程序員和數據分析員來保證數據完整性的一種方法,它是與表事件相關的特殊的存儲過程。
使用場景

問題 8:請說明 InnoDB 和 MyISAM 的區別

問題 9:innodb 引擎的特性

問題 10:請列舉 3 個以上表引擎
InnoDB、MyISAM、Memory

問題 11:請說明 varchar 和 text 的區別

問題 12:varchar(50) 中 50 的含義
最多存放 50 個字符,varchar(50)和 (200) 存儲 hello 所佔空間一樣,但後者在排序時會消耗更多內存,因爲 order by col 採用 fixed_length 計算 col 長度(memory 引擎也一樣)。

問題 13:int(20) 中 20 的含義
是指顯示字符的長度,不影響內部存儲,只是當定義了 ZEROFILL 時,前面補多少個 0

問題 14:簡單描述 MySQL 中,索引,主鍵,唯一索引,聯合索引的區別,對數據庫的性能有什麼影響?

知識點分析

此真題主要考察的是 MySQL 索引的基礎和類型,由此延伸出的知識點還包括如下內容:

下面我們就來將這些知識一網打盡

索引的基礎

創建索引的語法:

索引對性能的影響:

索引的使用場景:

索引的類型:
索引很多種類型,是在 MySQL 的存儲引擎實現的。

索引的區別:

MySQL 索引的創建原則

MySQL 索引的注意事項
1、聯合索引遵循前綴原則

KEY(a,b,c) WHERE a = 1 AND b = 2 AND c = 3 WHERE a = 1 AND b = 2 WHERE a = 1 #以上SQL語句可以用到索引 WHERE b = 2 AND c = 3 WHERE a = 1 AND c = 3 #以上SQL語句用不到索引

2、LIKE 查詢,% 不能在前

WHERE name LIKE "%wang%" #以上語句用不到索引,可以用外部的ElasticSearch、Lucene等全文搜索引擎替代。

3、列值爲空(NULL)時是可以使用索引的,但 MySQL 難以優化引用了可空列的查詢, 它會使索引、索引統計和值更加複雜。可空列需要更多的儲存空間,還需要在 MySQL 內部進行特殊處理。

4、如果 MySQL 估計使用索引比全表掃描更慢,會放棄使用索引,例如:
表中只有 100 條數據左右。對於 SQL 語句 WHERE id > 1 AND id < 100,MySQL 會優先考慮全表掃描。

5、如果關鍵詞 or 前面的條件中的列有索引,後面的沒有,所有列的索引都不會被用到。

6、列類型是字符串,查詢時一定要給值加引號,否則索引失效,例如:
列 name varchar(16),存儲了字符串 "100"
WHERE name = 100;
以上 SQL 語句能搜到,但無法用到索引。

MySQL 索引的原理

注: B+ 樹是一種樹數據結構,是一個n叉排序樹,每個節點通常有多個孩子,一棵B+樹包含根節點、內部節點和葉子節點。根節點可能是一個葉子節點,也可能是一個包含兩個或兩個以上孩子節點的節點。 B+ 樹通常用於數據庫和操作系統的文件系統中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系統都在使用B+樹作爲元數據索引。B+ 樹的特點是能夠保持數據穩定有序,其插入與修改擁有較穩定的對數時間複雜度。B+ 樹元素自底向上插入。

InnoDB 通過主鍵聚簇數據,如果沒有定義主鍵,會選擇一個唯一的非空索引代替,如果沒有這樣的索引,會隱式定義個主鍵作爲聚簇索引。
下圖形象說明了聚簇索引表 (InnoDB) 和普通的堆組織表 (MyISAM) 的區別:

最常問的 MySQL 面試題三——每個開發人員都應該知道
對於普通的堆組織表來說(右圖),表數據和索引是分別存儲的,主鍵索引和二級索引存儲上沒有任何區別。
而對於聚簇索引表來說(左圖),表數據是和主鍵一起存儲的,主鍵索引的葉結點存儲行數據,二級索引的葉結點存儲行的主鍵值。
聚簇索引表最大限度地提高了 I/O 密集型應用的性能,但它也有以下幾個限制:

二級索引的葉節點存儲的是主鍵值,而不是行指針,這是爲了減少當出現行移動或數據頁分裂時二級索引的維護工作,但會讓二級索引佔用更多的空間。

解題方法

在一些 MySQL 索引基礎考題中,我們可以輕鬆的通過索引基礎和類型來解決此類問題,對於一些索引創建注意事項方面的考點,我們可以通過索引創建原則和注意事項來解決。

問題 14:創建 MySQL 聯合索引應該注意什麼?
需遵循前綴原則

問題 15:列值爲 NULL 時,查詢是否會用到索引?
在 MySQL 裏 NULL 值的列也是走索引的。當然,如果計劃對列進行索引,就要儘量避免把它設置爲可空,MySQL 難以優化引用了可空列的查詢, 它會使索引、索引統計和值更加複雜。

問題 16:以下語句是否會應用索引:SELECT FROM users WHERE YEAR(adddate) < 2007;*
不會,因爲只要列涉及到運算,MySQL 就不會使用索引。

問題 17:MyISAM 索引實現?
MyISAM 存儲引擎使用 B+Tree 作爲索引結構,葉節點的 data 域存放的是數據記錄的地址。MyISAM 的索引方式也叫做非聚簇索引的,之所以這麼稱呼是爲了與 InnoDB 的聚簇索引區分。

問題 18:MyISAM 索引與 InnoDB 索引的區別?

問題 19:以下三條 sql 如何建索引,只建一條怎麼建?

WHERE a=1 AND b=1 WHERE b=1 WHERE b=1 ORDER BY time DESC

以順序 b,a,time 建立聯合索引,CREATE INDEX table1_b_a_time ON index_test01(b,a,time)。因爲最新 MySQL 版本會優化 WHERE 子句後面的列順序,以匹配聯合索引順序。

問題 20:有 A(id,sex,par,c1,c2),B(id,age,c1,c2) 兩張表,其中 A.id 與 B.id 關聯,現在要求寫出一條 SQL 語句,將 B 中 age>50 的記錄的 c1,c2 更新到 A 表中同一記錄中的 c1,c2 字段中
考點分析
這道題主要考察的是 MySQL 的關聯 UPDATE 語句
延伸考點:

針對剛纔這道題,答案可以是如下兩種形式的寫法:

UPDATE A,B SET A.c1 = B.c1, A.c2 = B.c2 WHERE A.id = B.id UPDATE A INNER JOIN B ON A.id=B.id SET A.c1 = B.c1,A.c2=B.c2 _--再加上B中age>50的條件:_ UPDATE A,B set A.c1 = B.c1, A.c2 = B.c2 WHERE A.id = B.id and B.age > 50; UPDATE A INNER JOIN B ON A.id = B.id set A.c1 = B.c1,A.c2 = B.c2 WHERE B.age > 50

MySQL 的關聯查詢語句

六種關聯查詢

SELECT * FROM A,B(,C)或者 SELECT * FROM A CROSS JOIN B (CROSS JOIN C) #沒有任何關聯條件,結果是笛卡爾積,結果集會很大,沒有意義,很少使用 內連接(INNER JOIN) SELECT * FROM A,B WHERE A.id=B.id或者 SELECT * FROM A INNER JOIN B ON A.id=B.id 多表中同時符合某種條件的數據記錄的集合,INNER JOIN可以縮寫爲JOIN

內連接分爲三類

外連接(LEFT JOIN/RIGHT JOIN)

聯合查詢(UNION 與 UNION ALL)

SELECT * FROM A UNION SELECT * FROM B UNION ...

全連接(FULL JOIN)

SELECT * FROM A LEFT JOIN B ON A.id=B.id UNION SELECT * FROM A RIGHT JOIN B ON A.id=B.id

嵌套查詢
用一條 SQL 語句得結果作爲另外一條 SQL 語句得條件,效率不好把握
SELECT * FROM A WHERE id IN (SELECT id FROM B)

解題方法

根據考題要搞清楚表的結果和多表之間的關係,根據想要的結果思考使用那種關聯方式,通常把要查詢的列先寫出來,然後分析這些列都屬於哪些表,才考慮使用關聯查詢

問題 21:
爲了記錄足球比賽的結果,設計表如下:
team:參賽隊伍表
match:賽程表
其中,match 賽程表中的 hostTeamID 與 guestTeamID 都和 team 表中的 teamID 關聯,查詢 2006-6-1 到 2006-7-1 之間舉行的所有比賽,並且用以下形式列出:拜仁 2:0 不萊梅 2006-6-21

首先列出需要查詢的列:
其次列出結果列:

初步寫一個基礎的 SQL:

SELECT hostTeamID,matchResult,matchTime guestTeamID from match where matchTime between "2006-6-1" and "2006-7-1";

通過外鍵聯表,完成最終 SQL:

select t1.teamName,m.matchResult,t2.teamName,m.matchTime from match as m left join team as t1 on m.hostTeamID = t1.teamID, left join team t2 on m.guestTeamID=t2.guestTeamID where m.matchTime between "2006-6-1" and "2006-7-1"

問題 22:UNION 與 UNION ALL 的區別?

問題 23:一個 6 億的表 a,一個 3 億的表 b,通過外鍵 tid 關聯,你如何最快的查詢出滿足條件的第 50000 到第 50200 中的這 200 條數據記錄。

select * from a,b where a.tid = b.id and a.tid>50000 limit 200;

select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;

問題 24:拷貝表 (拷貝數據, 源表名:a 目標表名:b)

insert into b(a, b, c) select d,e,f from a;

問題 25: Student(S#,Sname,Sage,Ssex) 學生表 Course(C#,Cname,T#) 課程表 SC(S#,C#,score) 成績表 Teacher(T#,Tname) 教師表 查詢沒學過 “葉平” 老師課的同學的學號、姓名

select Student.S#,Student.Sname from Student where S# not in (select distinct( SC.S#) from SC,Course,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname=’葉平’);

問題 26:隨機取出 10 條數據

SELECT * FROM users WHERE id >= ((SELECT MAX(id) FROM users)-(SELECT MIN(id) FROM users)) * RAND() + (SELECT MIN(id) FROM users) LIMIT 10 #此方法效率比直接用SELECT * FROM users order by rand() LIMIT 10高很多

問題 27:請簡述項目中優化 SQL 語句執行效率的方法,從哪些方面,SQL 語句性能如何分析?
考點分析:
這道題主要考察的是查找分析 SQL 語句查詢速度慢的方法

延伸考點:

如何查找查詢速度慢的原因
記錄慢查詢日誌,分析查詢日誌,不要直接打開慢查詢日誌進行分析,這樣比較浪費時間和精力,可以使用 pt-query-digest 工具進行分析

使用 show profile

set profiling=1;``開啓,服務器上所有執行語句會記錄執行時間,存到臨時表中 show profiles show profile for query 臨時表ID

使用 show status

show status 會返回一些計數器,show global status 會查看所有服務器級別的所有計數
有時根據這些計數,可以推測出哪些操作代價較高或者消耗時間多

show processlist

觀察是否有大量線程處於不正常的狀態或特徵

最常問的 MySQL 面試題五——每個開發人員都應該知道

使用 explain

分析單條 SQL 語句

優化查詢過程中的數據訪問

優化長難的查詢語句

優化特定類型的查詢語句

優化關聯查詢

優化子查詢

優化 LIMIT 分頁

優化 UNION 查詢

優化 WHERE 子句

解題方法

對於此類考題,先說明如何定位低效 SQL 語句,然後根據 SQL 語句可能低效的原因做排查,先從索引着手,如果索引沒有問題,考慮以上幾個方面,數據訪問的問題,長難查詢句的問題還是一些特定類型優化的問題,逐一回答。

SQL 語句優化的一些方法?

select id from t where num is null``可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:``select id from t where num=

select id from t where num=10 or num=20``可以這樣查詢:``select id from t where num=10 union all select id from t where num=20

select id from t where num in(1,2,3) ``對於連續的數值,能用 between 就不要用 in 了:``select id from t where num between 1 and 3

select id from t where num=@num``可以改爲強制查詢使用索引:``select id from t with(index(索引名)) where num=@num

select id from t where num/2=100``應改爲:``select id from t where num=100*2

select id from t where substring(name,1,3)=’abc’ ,name``以abc開頭的id應改爲: select id from t where name like ‘abc%’

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/sEhvinIua6wdTNjnwB7N0g