三萬字、91道MySQL面試題。 附PDF
文末領取面試題 高清PDF
資料庫基礎知識
1. 為什麼要使用資料庫
- 資料儲存在記憶體
優點:存取速度快
缺點:資料不能永久儲存
- 資料儲存在檔案
優點:資料永久儲存
缺點:1)速度比記憶體操作慢,頻繁的IO操作。2)查詢資料不方便
- 資料儲存在資料庫
1)資料永久儲存
2)使用SQL語句,查詢方便效率高。
3)管理資料方便
2. 什麼是SQL?
結構化查詢語言(Structured Query Language)簡稱SQL,是一種資料庫查詢語言。
作用:用於存取資料、查詢、更新和管理關係資料庫系統。
3. 什麼是MySQL?
MySQL是一個關係型資料庫管理系統,由瑞典MySQL AB 公司開發,屬於 Oracle 旗下產品。MySQL 是最流行的關係型資料庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關係資料庫管理系統) 應用軟體之一。在Java企業級開發中非常常用,因為 MySQL 是開源免費的,並且方便擴充套件。
4. 資料庫三大正規化是什麼
第一正規化:每個列都不可以再拆分。
第二正規化:在第一正規化的基礎上,非主鍵列完全依賴於主鍵,而不能是依賴於主鍵的一部分。
第三正規化:在第二正規化的基礎上,非主鍵列只依賴於主鍵,不依賴於其他非主鍵。
在設計資料庫結構的時候,要儘量遵守三正規化,如果不遵守,必須有足夠的理由。比如效能。事實上我們經常會為了效能而妥協資料庫的設計。
5. mysql有關許可權的表都有哪幾個
MySQL伺服器通過許可權表來控制使用者對資料庫的訪問,許可權表存放在mysql資料庫裡,由mysql_install_db指令碼初始化。這些許可權表分別user,db,table_priv,columns_priv和host。下面分別介紹一下這些表的結構和內容:
- user許可權表:記錄允許連線到伺服器的使用者帳號資訊,裡面的許可權是全域性級的。
- db許可權表:記錄各個帳號在各個資料庫上的操作許可權。
- table_priv許可權表:記錄資料表級的操作許可權。
- columns_priv許可權表:記錄資料列級的操作許可權。
- host許可權表:配合db許可權表對給定主機上資料庫級操作許可權作更細緻的控制。這個許可權表不受GRANT和REVOKE語句的影響。
6. MySQL的binlog有有幾種錄入格式?分別有什麼區別?
有三種格式,statement,row和mixed。
- statement模式下,每一條會修改資料的sql都會記錄在binlog中。不需要記錄每一行的變化,減少了binlog日誌量,節約了IO,提高效能。由於sql的執行是有上下文的,因此在儲存的時候需要儲存相關的資訊,同時還有一些使用了函式之類的語句無法被記錄複製。
- row級別下,不記錄sql語句上下文相關資訊,僅儲存哪條記錄被修改。記錄單元為每一行的改動,基本是可以全部記下來但是由於很多操作,會導致大量行的改動(比如alter table),因此這種模式的檔案儲存的資訊太多,日誌量太大。
- mixed,一種折中的方案,普通操作使用statement記錄,當無法使用statement的時候使用row。
此外,新版的MySQL中對row級別也做了一些優化,當表結構發生變化的時候,會記錄語句而不是逐行記錄。
資料型別
mysql有哪些資料型別
分類 | 型別名稱 | 說明 |
---|---|---|
整數型別 | tinyInt | 很小的整數(8位二進位制) |
smallint | 小的整數(16位二進位制) | |
mediumint | 中等大小的整數(24位二進位制) | |
int(integer) | 普通大小的整數(32位二進位制) | |
小數型別 | float | 單精度浮點數 |
double | 雙精度浮點數 | |
decimal(m,d) | 壓縮嚴格的定點數 | |
日期型別 | year | YYYY 1901~2155 |
time | HH:MM:SS -838:59:59~838:59:59 | |
date | YYYY-MM-DD 1000-01-01~9999-12-3 | |
datetime | YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~ 9999-12-31 23:59:59 | |
timestamp | YYYY-MM-DD HH:MM:SS 19700101 00:00:01 UTC~2038-01-19 03:14:07UTC | |
文字、二進位制型別 | CHAR(M) | M為0~255之間的整數 |
VARCHAR(M) | M為0~65535之間的整數 | |
TINYBLOB | 允許長度0~255位元組 | |
BLOB | 允許長度0~65535位元組 | |
MEDIUMBLOB | 允許長度0~167772150位元組 | |
LONGBLOB | 允許長度0~4294967295位元組 | |
TINYTEXT | 允許長度0~255位元組 | |
TEXT | 允許長度0~65535位元組 | |
MEDIUMTEXT | 允許長度0~167772150位元組 | |
LONGTEXT | 允許長度0~4294967295位元組 | |
VARBINARY(M) | 允許長度0~M個位元組的變長位元組字串 | |
BINARY(M) | 允許長度0~M個位元組的定長位元組字串 |
- 1、整數型別,包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分別表示1位元組、2位元組、3位元組、4位元組、8位元組整數。任何整數型別都可以加上UNSIGNED屬性,表示資料是無符號的,即非負整數。 長度:整數型別可以被指定長度,例如:INT(11)表示長度為11的INT型別。長度在大多數場景是沒有意義的,它不會限制值的合法範圍,只會影響顯示字元的個數,而且需要和UNSIGNED ZEROFILL屬性配合使用才有意義。 例子,假定型別設定為INT(5),屬性為UNSIGNED ZEROFILL,如果使用者插入的資料為12的話,那麼資料庫實際儲存資料為00012。
- 2、實數型別,包括FLOAT、DOUBLE、DECIMAL。 DECIMAL可以用於儲存比BIGINT還大的整型,能儲存精確的小數。 而FLOAT和DOUBLE是有取值範圍的,並支援使用標準的浮點進行近似計算。 計算時FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字串進行處理。
- 3、字串型別,包括VARCHAR、CHAR、TEXT、BLOB VARCHAR用於儲存可變長字串,它比定長型別更節省空間。 VARCHAR使用額外1或2個位元組儲存字串長度。列長度小於255位元組時,使用1位元組表示,否則使用2位元組表示。 VARCHAR儲存的內容超出設定的長度時,內容會被截斷。 CHAR是定長的,根據定義的字串長度分配足夠的空間。 CHAR會根據需要使用空格進行填充方便比較。 CHAR適合儲存很短的字串,或者所有值都接近同一個長度。 CHAR儲存的內容超出設定的長度時,內容同樣會被截斷。 使用策略: 對於經常變更的資料來說,CHAR比VARCHAR更好,因為CHAR不容易產生碎片。 對於非常短的列,CHAR比VARCHAR在儲存空間上更有效率。 使用時要注意只分配需要的空間,更長的列排序時會消耗更多記憶體。 儘量避免使用TEXT/BLOB型別,查詢時會使用臨時表,導致嚴重的效能開銷。
- 4、列舉型別(ENUM),把不重複的資料儲存為一個預定義的集合。 有時可以使用ENUM代替常用的字串型別。 ENUM儲存非常緊湊,會把列表值壓縮到一個或兩個位元組。 ENUM在內部儲存時,其實存的是整數。 儘量避免使用數字作為ENUM列舉的常量,因為容易混亂。 排序是按照內部儲存的整數
- 5、日期和時間型別,儘量使用timestamp,空間效率高於datetime, 用整數儲存時間戳通常不方便處理。 如果需要儲存微妙,可以使用bigint儲存。 看到這裡,這道真題是不是就比較容易回答了。
引擎
1. MySQL儲存引擎MyISAM與InnoDB區別
儲存引擎Storage engine:MySQL中的資料、索引以及其他物件是如何儲存的,是一套檔案系統的實現。
常用的儲存引擎有以下:
- Innodb引擎:Innodb引擎提供了對資料庫ACID事務的支援。並且還提供了行級鎖和外來鍵的約束。它的設計的目標就是處理大資料容量的資料庫系統。
- MyIASM引擎(原本Mysql的預設引擎):不提供事務的支援,也不支援行級鎖和外來鍵。
- MEMORY引擎:所有的資料都在記憶體中,資料的處理速度快,但是安全性不高。
2. MyISAM與InnoDB區別
MyISAM | Innodb | |
---|---|---|
儲存結構 | 每張表被存放在三個檔案:frm-表格定義、MYD(MYData)-資料檔案、MYI(MYIndex)-索引檔案 | 所有的表都儲存在同一個資料檔案中(也可能是多個檔案,或者是獨立的表空間檔案),InnoDB表的大小隻受限於作業系統檔案的大小,一般為2GB |
儲存空間 | MyISAM可被壓縮,儲存空間較小 | InnoDB的表需要更多的記憶體和儲存,它會在主記憶體中建立其專用的緩衝池用於高速緩衝資料和索引 |
可移植性、備份及恢復 | 由於MyISAM的資料是以檔案的形式儲存,所以在跨平臺的資料轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作 | 免費的方案可以是拷貝資料檔案、備份 binlog,或者用 mysqldump,在資料量達到幾十G的時候就相對痛苦了 |
檔案格式 | 資料和索引是分別儲存的,資料.MYD,索引.MYI | 資料和索引是集中儲存的,.ibd |
記錄儲存順序 | 按記錄插入順序儲存 | 按主鍵大小有序插入 |
外來鍵 | 不支援 | 支援 |
事務 | 不支援 | 支援 |
鎖支援(鎖是避免資源爭用的一個機制,MySQL鎖對使用者幾乎是透明的) | 表級鎖定 | 行級鎖定、表級鎖定,鎖定力度小併發能力高 |
SELECT | MyISAM更優 | |
INSERT、UPDATE、DELETE | InnoDB更優 | |
select count(*) | myisam更快,因為myisam內部維護了一個計數器,可以直接調取。 | |
索引的實現方式 | B+樹索引,myisam 是堆表 | B+樹索引,Innodb 是索引組織表 |
雜湊索引 | 不支援 | 支援 |
全文索引 | 支援 | 不支援 |
3.MyISAM索引與InnoDB索引的區別?**
- InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
- InnoDB的主鍵索引的葉子節點儲存著行資料,因此主鍵索引非常高效。
- MyISAM索引的葉子節點儲存的是行資料地址,需要再定址一次才能得到資料。
- InnoDB非主鍵索引的葉子節點儲存的是主鍵和其他帶索引的列資料,因此查詢時做到覆蓋索引會非常高效。
4. InnoDB引擎的4大特性
- 插入緩衝(insert buffer)
- 二次寫(double write)
- 自適應雜湊索引(ahi)
- 預讀(read ahead)
5. 儲存引擎選擇
如果沒有特別的需求,使用預設的Innodb即可。
MyISAM:以讀寫插入為主的應用程式,比如部落格系統、新聞入口網站。
Innodb:更新(刪除)操作頻率也高,或者要保證資料的完整性;併發量高,支援事務和外來鍵。比如OA自動化辦公系統。
索引
1. 什麼是索引?
索引是一種特殊的檔案(InnoDB資料表上的索引是表空間的一個組成部分),它們包含著對資料表裡所有記錄的引用指標。
索引是一種資料結構。資料庫索引,是資料庫管理系統中一個排序的資料結構,以協助快速查詢、更新資料庫表中資料。索引的實現通常使用B樹及其變種B+樹。
更通俗的說,索引就相當於目錄。為了方便查詢書中的內容,通過對內容建立索引形成目錄。索引是一個檔案,它是要佔據物理空間的。
2. 索引有哪些優缺點?
索引的優點
- 可以大大加快資料的檢索速度,這也是建立索引的最主要的原因。
- 通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的效能。
索引的缺點
- 時間方面:建立索引和維護索引要耗費時間,具體地,當對錶中的資料進行增加、刪除和修改的時候,索引也要動態的維護,會降低增/改/刪的執行效率;
- 空間方面:索引需要佔物理空間。
3. 索引使用場景(重點)
where
上圖中,根據id查詢記錄,因為id欄位僅建立了主鍵索引,因此此SQL執行可選的索引只有主鍵索引,如果有多個,最終會選一個較優的作為檢索的依據。
-- 增加一個沒有建立索引的欄位
alter table innodb1 add sex char(1);
-- 按sex檢索時可選的索引為null
EXPLAIN SELECT * from innodb1 where sex='男';
可以嘗試在一個欄位未建立索引時,根據該欄位查詢的效率,然後對該欄位建立索引(alter table 表名 add index(欄位名)),同樣的SQL執行的效率,你會發現查詢效率會有明顯的提升(資料量越大越明顯)。
order by
當我們使用order by將查詢結果按照某個欄位排序時,如果該欄位沒有建立索引,那麼執行計劃會將查詢出的所有資料使用外部排序(將資料從硬碟分批讀取到記憶體使用內部排序,最後合併排序結果),這個操作是很影響效能的,因為需要將查詢涉及到的所有資料從磁碟中讀到記憶體(如果單條資料過大或者資料量過多都會降低效率),更無論讀到記憶體之後的排序了。
但是如果我們對該欄位建立索引alter table 表名 add index(欄位名),那麼由於索引本身是有序的,因此直接按照索引的順序和對映關係逐條取出資料即可。而且如果分頁的,那麼只用取出索引表某個範圍內的索引對應的資料,而不用像上述那取出所有資料進行排序再返回某個範圍內的資料。(從磁碟取資料是最影響效能的)
join
對join語句匹配關係(on)涉及的欄位建立索引能夠提高效率
索引覆蓋
如果要查詢的欄位都建立過索引,那麼引擎會直接在索引表中查詢而不會訪問原始資料(否則只要有一個欄位沒有建立索引就會做全表掃描),這叫索引覆蓋。因此我們需要儘可能的在select後只寫必要的查詢欄位,以增加索引覆蓋的機率。
這裡值得注意的是不要想著為每個欄位建立索引,因為優先使用索引的優勢就在於其體積小。
4. 索引有哪幾種類型?
主鍵索引: 資料列不允許重複,不允許為NULL,一個表只能有一個主鍵。
唯一索引: 資料列不允許重複,允許為NULL值,一個表允許多個列建立唯一索引。
- 可以通過 ALTER TABLE table_name ADD UNIQUE (column); 建立唯一索引
- 可以通過 ALTER TABLE table_name ADD UNIQUE (column1,column2); 建立唯一組合索引
普通索引: 基本的索引型別,沒有唯一性的限制,允許為NULL值。
- 可以通過ALTER TABLE table_name ADD INDEX index_name (column);建立普通索引
- 可以通過ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);建立組合索引
全文索引:是目前搜尋引擎使用的一種關鍵技術。
- 可以通過ALTER TABLE table_name ADD FULLTEXT (column);建立全文索引
5. 索引的資料結構(b樹,hash)
索引的資料結構和具體儲存引擎的實現有關,在MySQL中使用較多的索引有Hash索引,B+樹索引等,而我們經常使用的InnoDB儲存引擎的預設索引實現為:B+樹索引。對於雜湊索引來說,底層的資料結構就是雜湊表,因此在絕大多數需求為單條記錄查詢的時候,可以選擇雜湊索引,查詢效能最快;其餘大部分場景,建議選擇BTree索引。
1)B樹索引
mysql通過儲存引擎取資料,基本上90%的人用的就是InnoDB了,按照實現方式分,InnoDB的索引型別目前只有兩種:BTREE(B樹)索引和HASH索引。B樹索引是Mysql資料庫中使用最頻繁的索引型別,基本所有儲存引擎都支援BTree索引。通常我們說的索引不出意外指的就是(B樹)索引(實際是用B+樹實現的,因為在查看錶索引時,mysql一律列印BTREE,所以簡稱為B樹索引)
查詢方式:
主鍵索引區:PI(關聯儲存的時資料的地址)按主鍵查詢,
普通索引區:si(關聯的id的地址,然後再到達上面的地址)。所以按主鍵查詢,速度最快
B+tree性質:
1.)n棵子tree的節點包含n個關鍵字,不用來儲存資料而是儲存資料的索引。
2.)所有的葉子結點中包含了全部關鍵字的資訊,及指向含這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大順序連結。
3.)所有的非終端結點可以看成是索引部分,結點中僅含其子樹中的最大(或最小)關鍵字。
4.)B+ 樹中,資料物件的插入和刪除僅在葉節點上進行。
5.)B+樹有2個頭指標,一個是樹的根節點,一個是最小關鍵碼的葉節點。
2)雜湊索引
簡要說下,類似於資料結構中簡單實現的HASH表(散列表)一樣,當我們在mysql中用雜湊索引時,主要就是通過Hash演算法(常見的Hash演算法有直接定址法、平方取中法、摺疊法、除數取餘法、隨機數法),將資料庫欄位資料轉換成定長的Hash值,與這條資料的行指標一併存入Hash表的對應位置;如果發生Hash碰撞(兩個不同關鍵字的Hash值相同),則在對應Hash鍵下以連結串列形式儲存。當然這只是簡略模擬圖。
6. 索引的基本原理
索引用來快速地尋找那些具有特定值的記錄。如果沒有索引,一般來說執行查詢時遍歷整張表。
索引的原理很簡單,就是把無序的資料變成有序的查詢
- 把建立了索引的列的內容進行排序
- 對排序結果生成倒排表
- 在倒排表內容上拼上資料地址鏈
- 在查詢的時候,先拿到倒排表內容,再取出資料地址鏈,從而拿到具體資料
7. 索引演算法有哪些?
索引演算法有 BTree演算法和Hash演算法
BTree演算法
BTree是最常用的mysql資料庫索引演算法,也是mysql預設的演算法。因為它不僅可以被用在=,>,>=,<,<=和between這些比較操作符上,而且還可以用於like操作符,只要它的查詢條件是一個不以萬用字元開頭的常量, 例如:
-- 只要它的查詢條件是一個不以萬用字元開頭的常量
select * from user where name like 'jack%';
-- 如果一萬用字元開頭,或者沒有使用常量,則不會使用索引,例如:
select * from user where name like '%jack';
Hash演算法
Hash Hash索引只能用於對等比較,例如=,<=>(相當於=)操作符。由於是一次定位資料,不像BTree索引需要從根節點到枝節點,最後才能訪問到頁節點這樣多次IO訪問,所以檢索效率遠高於BTree索引。
8. 索引設計的原則?
- 適合索引的列是出現在where子句中的列,或者連線子句中指定的列
- 基數較小的類,索引效果較差,沒有必要在此列建立索引
- 使用短索引,如果對長字串列進行索引,應該指定一個字首長度,這樣能夠節省大量索引空間
- 不要過度索引。索引需要額外的磁碟空間,並降低寫操作的效能。在修改表內容的時候,索引會進行更新甚至重構,索引列越多,這個時間就會越長。所以只保持需要的索引有利於查詢即可。
9. 建立索引的原則(重中之重)
索引雖好,但也不是無限制的使用,最好符合一下幾個原則
1) 最左字首匹配原則,組合索引非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。
2)較頻繁作為查詢條件的欄位才去建立索引
3)更新頻繁欄位不適合建立索引
4)若是不能有效區分資料的列不適合做索引列(如性別,男女未知,最多也就三種,區分度實在太低)
5)儘量的擴充套件索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可。
6)定義有外來鍵的資料列一定要建立索引。
7)對於那些查詢中很少涉及的列,重複值比較多的列不要建立索引。
8)對於定義為text、image和bit的資料型別的列不要建立索引。
10. 建立索引的三種方式,刪除索引
第一種方式:在執行CREATE TABLE時建立索引
CREATE TABLE user_index2 (
id INT auto_increment PRIMARY KEY,
first_name VARCHAR (16),
last_name VARCHAR (16),
id_card VARCHAR (18),
information text,
KEY name (first_name, last_name),
FULLTEXT KEY (information),
UNIQUE KEY (id_card)
);
第二種方式:使用ALTER TABLE命令去增加索引
ALTER TABLE table_name ADD INDEX index_name (column_list);
- 1
ALTER TABLE用來建立普通索引、UNIQUE索引或PRIMARY KEY索引。
其中table_name是要增加索引的表名,column_list指出對哪些列進行索引,多列時各列之間用逗號分隔。
索引名index_name可自己命名,預設時,MySQL將根據第一個索引列賦一個名稱。另外,ALTER TABLE允許在單個語句中更改多個表,因此可以在同時建立多個索引。
第三種方式:使用CREATE INDEX命令建立
CREATE INDEX index_name ON table_name (column_list);
CREATE INDEX可對錶增加普通索引或UNIQUE索引。(但是,不能建立PRIMARY KEY索引)
刪除索引
根據索引名刪除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名
alter table user_index drop KEY name;
alter table user_index drop KEY id_card;
alter table user_index drop KEY information;
刪除主鍵索引:alter table 表名 drop primary key(因為主鍵只有一個)。這裡值得注意的是,如果主鍵自增長,那麼不能直接執行此操作(自增長依賴於主鍵索引):
需要取消自增長再行刪除:
alter table user_index
-- 重新定義欄位
MODIFY id int,
drop PRIMARY KEY
但通常不會刪除主鍵,因為設計主鍵一定與業務邏輯無關。
11. 建立索引時需要注意什麼?
- 非空欄位:應該指定列為NOT NULL,除非你想儲存NULL。在mysql中,含有空值的列很難進行查詢優化,因為它們使得索引、索引的統計資訊以及比較運算更加複雜。你應該用0、一個特殊的值或者一個空串代替空值;
- 取值離散大的欄位:(變數各個取值之間的差異程度)的列放到聯合索引的前面,可以通過count()函式檢視欄位的差異值,返回值越大說明欄位的唯一值越多欄位的離散程度高;
- 索引欄位越小越好:資料庫的資料儲存以頁為單位一頁儲存的資料越多一次IO操作獲取的資料越大效率越高。
12. 使用索引查詢一定能提高查詢的效能嗎?為什麼
通常,通過索引查詢資料比全表掃描要快。但是我們也必須注意到它的代價。
- 索引需要空間來儲存,也需要定期維護, 每當有記錄在表中增減或索引列被修改時,索引本身也會被修改。這意味著每條記錄的INSERT,DELETE,UPDATE將為此多付出4,5 次的磁碟I/O。因為索引需要額外的儲存空間和處理,那些不必要的索引反而會使查詢反應時間變慢。使用索引查詢不一定能提高查詢效能,索引範圍查詢(INDEX RANGE SCAN)適用於兩種情況:
- 基於一個範圍的檢索,一般查詢返回結果集小於表中記錄數的30%
- 基於非唯一性索引的檢索
13. 百萬級別或以上的資料如何刪除
關於索引:由於索引需要額外的維護成本,因為索引檔案是單獨存在的檔案,所以當我們對資料的增加,修改,刪除,都會產生額外的對索引檔案的操作,這些操作需要消耗額外的IO,會降低增/改/刪的執行效率。所以,在我們刪除資料庫百萬級別資料的時候,查詢MySQL官方手冊得知刪除資料的速度和建立的索引數量是成正比的。
- 所以我們想要刪除百萬資料的時候可以先刪除索引(此時大概耗時三分多鐘)
- 然後刪除其中無用資料(此過程需要不到兩分鐘)
- 刪除完成後重新建立索引(此時資料較少了)建立索引也非常快,約十分鐘左右。
- 與之前的直接刪除絕對是要快速很多,更別說萬一刪除中斷,一切刪除會回滾。那更是坑了。
14. 字首索引
語法:index(field(10)),使用欄位值的前10個字元建立索引,預設是使用欄位的全部內容建立索引。
前提:字首的標識度高。比如密碼就適合建立字首索引,因為密碼幾乎各不相同。
實操的難度:在於字首擷取的長度。
我們可以利用select count(*)/count(distinct left(password,prefixLen));,通過從調整prefixLen的值(從1自增)檢視不同字首長度的一個平均匹配度,接近1時就可以了(表示一個密碼的前prefixLen個字元幾乎能確定唯一一條記錄)
15. 什麼是最左字首原則?什麼是最左匹配原則
- 顧名思義,就是最左優先,在建立多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。
- 最左字首匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。
- =和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式
16. B樹和B+樹的區別
- 在B樹中,你可以將鍵和值存放在內部節點和葉子節點;但在B+樹中,內部節點都是鍵,沒有值,葉子節點同時存放鍵和值。
- B+樹的葉子節點有一條鏈相連,而B樹的葉子節點各自獨立。
17. 使用B樹的好處
B樹可以在內部節點同時儲存鍵和值,因此,把頻繁訪問的資料放在靠近根節點的地方將會大大提高熱點資料的查詢效率。這種特性使得B樹在特定資料重複多次查詢的場景中更加高效。
18. 使用B+樹的好處
由於B+樹的內部節點只存放鍵,不存放值,因此,一次讀取,可以在記憶體頁中獲取更多的鍵,有利於更快地縮小查詢範圍。B+樹的葉節點由一條鏈相連,因此,當需要進行一次全資料遍歷的時候,B+樹只需要使用O(logN)時間找到最小的一個節點,然後通過鏈進行O(N)的順序遍歷即可。而B樹則需要對樹的每一層進行遍歷,這會需要更多的記憶體置換次數,因此也就需要花費更多的時間
19. Hash索引和B+樹所有有什麼區別或者說優劣呢?
首先要知道Hash索引和B+樹索引的底層實現原理:
hash索引底層就是hash表,進行查詢時,呼叫一次hash函式就可以獲取到相應的鍵值,之後進行回表查詢獲得實際資料。B+樹底層實現是多路平衡查詢樹。對於每一次的查詢都是從根節點出發,查詢到葉子節點方可以獲得所查鍵值,然後根據查詢判斷是否需要回表查詢資料。
那麼可以看出他們有以下的不同:
- hash索引進行等值查詢更快(一般情況下),但是卻無法進行範圍查詢。
因為在hash索引中經過hash函式建立索引之後,索引的順序與原順序無法保持一致,不能支援範圍查詢。而B+樹的的所有節點皆遵循(左節點小於父節點,右節點大於父節點,多叉樹也類似),天然支援範圍。
- hash索引不支援使用索引進行排序,原理同上。
- hash索引不支援模糊查詢以及多列索引的最左字首匹配。原理也是因為hash函式的不可預測。AAAA和AAAAB的索引沒有相關性。
- hash索引任何時候都避免不了回表查詢資料,而B+樹在符合某些條件(聚簇索引,覆蓋索引等)的時候可以只通過索引完成查詢。
- hash索引雖然在等值查詢上較快,但是不穩定。效能不可預測,當某個鍵值存在大量重複的時候,發生hash碰撞,此時效率可能極差。而B+樹的查詢效率比較穩定,對於所有的查詢都是從根節點到葉子節點,且樹的高度較低。
因此,在大多數情況下,直接選擇B+樹索引可以獲得穩定且較好的查詢速度。而不需要使用hash索引。
20. 資料庫為什麼使用B+樹而不是B樹
- B樹只適合隨機檢索,而B+樹同時支援隨機檢索和順序檢索;
- B+樹空間利用率更高,可減少I/O次數,磁碟讀寫代價更低。一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。這樣的話,索引查詢過程中就要產生磁碟I/O消耗。B+樹的內部結點並沒有指向關鍵字具體資訊的指標,只是作為索引使用,其內部結點比B樹小,盤塊能容納的結點中關鍵字數量更多,一次性讀入記憶體中可以查詢的關鍵字也就越多,相對的,IO讀寫次數也就降低了。而IO讀寫次數是影響索引檢索效率的最大因素;
- B+樹的查詢效率更加穩定。B樹搜尋有可能會在非葉子結點結束,越靠近根節點的記錄查詢時間越短,只要找到關鍵字即可確定記錄的存在,其效能等價於在關鍵字全集內做一次二分查詢。而在B+樹中,順序檢索比較明顯,隨機檢索時,任何關鍵字的查詢都必須走一條從根節點到葉節點的路,所有關鍵字的查詢路徑長度相同,導致每一個關鍵字的查詢效率相當。
- B-樹在提高了磁碟IO效能的同時並沒有解決元素遍歷的效率低下的問題。B+樹的葉子節點使用指標順序連線在一起,只要遍歷葉子節點就可以實現整棵樹的遍歷。而且在資料庫中基於範圍的查詢是非常頻繁的,而B樹不支援這樣的操作。
- 增刪檔案(節點)時,效率更高。因為B+樹的葉子節點包含所有關鍵字,並以有序的連結串列結構儲存,這樣可很好提高增刪效率。
21. B+樹在滿足聚簇索引和覆蓋索引的時候不需要回表查詢資料
在B+樹的索引中,葉子節點可能儲存了當前的key值,也可能儲存了當前的key值以及整行的資料,這就是聚簇索引和非聚簇索引。在InnoDB中,只有主鍵索引是聚簇索引,如果沒有主鍵,則挑選一個唯一鍵建立聚簇索引。如果沒有唯一鍵,則隱式的生成一個鍵來建立聚簇索引。
當查詢使用聚簇索引時,在對應的葉子節點,可以獲取到整行資料,因此不用再次進行回表查詢。
22. 什麼是聚簇索引?何時使用聚簇索引與非聚簇索引
- 聚簇索引:將資料儲存與索引放到了一塊,找到索引也就找到了資料
- 非聚簇索引:將資料儲存於索引分開結構,索引結構的葉子節點指向了資料的對應行,myisam通過key_buffer把索引先快取到記憶體中,當需要訪問資料時(通過索引訪問資料),在記憶體中直接搜尋索引,然後通過索引找到磁碟相應資料,這也就是為什麼索引不在key buffer命中時,速度慢的原因
澄清一個概念:innodb中,在聚簇索引之上建立的索引稱之為輔助索引,輔助索引訪問資料總是需要二次查詢,非聚簇索引都是輔助索引,像複合索引、字首索引、唯一索引,輔助索引葉子節點儲存的不再是行的物理位置,而是主鍵值
何時使用聚簇索引與非聚簇索引
23. 非聚簇索引一定會回表查詢嗎?
不一定,這涉及到查詢語句所要求的欄位是否全部命中了索引,如果全部命中了索引,那麼就不必再進行回表查詢。
舉個簡單的例子,假設我們在員工表的年齡上建立了索引,那麼當進行select age from employee where age < 20的查詢時,在索引的葉子節點上,已經包含了age資訊,不會再次進行回表查詢。
24. 聯合索引是什麼?為什麼需要注意聯合索引中的順序?
MySQL可以使用多個欄位同時建立一個索引,叫做聯合索引。在聯合索引中,如果想要命中索引,需要按照建立索引時的欄位順序挨個使用,否則無法命中索引。
具體原因為:
MySQL使用索引時需要索引有序,假設現在建立了"name,age,school"的聯合索引,那麼索引的排序為: 先按照name排序,如果name相同,則按照age排序,如果age的值也相等,則按照school進行排序。
當進行查詢時,此時索引僅僅按照name嚴格有序,因此必須首先使用name欄位進行等值查詢,之後對於匹配到的列而言,其按照age欄位嚴格有序,此時可以使用age欄位用做索引查詢,以此類推。因此在建立聯合索引的時候應該注意索引列的順序,一般情況下,將查詢需求頻繁或者欄位選擇性高的列放在前面。此外可以根據特例的查詢或者表結構進行單獨的調整。
事務
1. 什麼是資料庫事務?
事務是一個不可分割的資料庫操作序列,也是資料庫併發控制的基本單位,其執行的結果必須使資料庫從一種一致性狀態變到另一種一致性狀態。事務是邏輯上的一組操作,要麼都執行,要麼都不執行。
事務最經典也經常被拿出來說例子就是轉賬了。
假如小明要給小紅轉賬1000元,這個轉賬會涉及到兩個關鍵操作就是:將小明的餘額減少1000元,將小紅的餘額增加1000元。萬一在這兩個操作之間突然出現錯誤比如銀行系統崩潰,導致小明餘額減少而小紅的餘額沒有增加,這樣就不對了。事務就是保證這兩個關鍵操作要麼都成功,要麼都要失敗。
2. 事物的四大特性(ACID)介紹一下?
關係性資料庫需要遵循ACID規則,具體內容如下:
- 原子性:事務是最小的執行單位,不允許分割。事務的原子性確保動作要麼全部完成,要麼完全不起作用;
- 一致性:執行事務前後,資料保持一致,多個事務對同一個資料讀取的結果是相同的;
- 隔離性:併發訪問資料庫時,一個使用者的事務不被其他事務所幹擾,各併發事務之間資料庫是獨立的;
- 永續性:一個事務被提交之後。它對資料庫中資料的改變是持久的,即使資料庫發生故障也不應該對其有任何影響。
3. 什麼是髒讀?幻讀?不可重複讀?
- 髒讀(Drity Read):某個事務已更新一份資料,另一個事務在此時讀取了同一份資料,由於某些原因,前一個RollBack了操作,則後一個事務所讀取的資料就會是不正確的。
- 不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中資料不一致,這可能是兩次查詢過程中間插入了一個事務更新的原有的資料。
- 幻讀(Phantom Read):在一個事務的兩次查詢中資料筆數不一致,例如有一個事務查詢了幾列(Row)資料,而另一個事務卻在此時插入了新的幾列資料,先前的事務在接下來的查詢中,就會發現有幾列資料是它先前所沒有的。
4. 什麼是事務的隔離級別?MySQL的預設隔離級別是什麼?
為了達到事務的四大特性,資料庫定義了4種不同的事務隔離級別,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決髒讀、不可重複讀、幻讀這幾類問題。
隔離級別 | 髒讀 | 不可重複讀 | 幻影讀 |
---|---|---|---|
READ-UNCOMMITTED | √ | √ | √ |
READ-COMMITTED | × | √ | √ |
REPEATABLE-READ | × | × | √ |
SERIALIZABLE | × | × | × |
SQL 標準定義了四個隔離級別:
- READ-UNCOMMITTED(讀取未提交):最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀。
- READ-COMMITTED(讀取已提交):允許讀取併發事務已經提交的資料,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生。
- REPEATABLE-READ(可重複讀):對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生。
- SERIALIZABLE(可序列化):最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。
這裡需要注意的是:Mysql 預設採用的 REPEATABLE_READ隔離級別 Oracle 預設採用的 READ_COMMITTED隔離級別
事務隔離機制的實現基於鎖機制和併發排程。其中併發排程使用的是MVVC(多版本併發控制),通過儲存修改的舊版本資訊來支援併發一致性讀和回滾等特性。
因為隔離級別越低,事務請求的鎖越少,所以大部分資料庫系統的隔離級別都是READ-COMMITTED(讀取提交內容):,但是你要知道的是InnoDB 儲存引擎預設使用 REPEATABLE-READ(可重讀)並不會有任何效能損失。
InnoDB 儲存引擎在 分散式事務 的情況下一般會用到SERIALIZABLE(可序列化)隔離級別。
鎖
1. 對MySQL的鎖瞭解嗎
當資料庫有併發事務的時候,可能會產生資料的不一致,這時候需要一些機制來保證訪問的次序,鎖機制就是這樣的一個機制。
就像酒店的房間,如果大家隨意進出,就會出現多人搶奪同一個房間的情況,而在房間上裝上鎖,申請到鑰匙的人才可以入住並且將房間鎖起來,其他人只有等他使用完畢才可以再次使用。
2. 隔離級別與鎖的關係
在Read Uncommitted級別下,讀取資料不需要加共享鎖,這樣就不會跟被修改的資料上的排他鎖衝突
在Read Committed級別下,讀操作需要加共享鎖,但是在語句執行完以後釋放共享鎖;
在Repeatable Read級別下,讀操作需要加共享鎖,但是在事務提交之前並不釋放共享鎖,也就是必須等待事務執行完畢以後才釋放共享鎖。
SERIALIZABLE 是限制性最強的隔離級別,因為該級別鎖定整個範圍的鍵,並一直持有鎖,直到事務完成。
3. 按照鎖的粒度分資料庫鎖有哪些?鎖機制與InnoDB鎖演算法
在關係型資料庫中,可以按照鎖的粒度把資料庫鎖分為行級鎖(INNODB引擎)、表級鎖(MYISAM引擎)和頁級鎖(BDB引擎 )。
MyISAM和InnoDB儲存引擎使用的鎖:
- MyISAM採用表級鎖(table-level locking)。
- InnoDB支援行級鎖(row-level locking)和表級鎖,預設為行級鎖
行級鎖,表級鎖和頁級鎖對比
行級鎖 行級鎖是Mysql中鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖能大大減少資料庫操作的衝突。其加鎖粒度最小,但加鎖的開銷也最大。行級鎖分為共享鎖 和 排他鎖。
特點:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。
表級鎖 表級鎖是MySQL中鎖定粒度最大的一種鎖,表示對當前操作的整張表加鎖,它實現簡單,資源消耗較少,被大部分MySQL引擎支援。最常使用的MYISAM與INNODB都支援表級鎖定。表級鎖定分為表共享讀鎖(共享鎖)與表獨佔寫鎖(排他鎖)。
特點:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發出鎖衝突的概率最高,併發度最低。
頁級鎖 頁級鎖是MySQL中鎖定粒度介於行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。
特點:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般
4. 從鎖的類別上分MySQL都有哪些鎖呢?像上面那樣子進行鎖定豈不是有點阻礙併發效率了
從鎖的類別上來講,有共享鎖和排他鎖。
共享鎖: 又叫做讀鎖。當用戶要進行資料的讀取時,對資料加上共享鎖。共享鎖可以同時加上多個。
排他鎖: 又叫做寫鎖。當用戶要進行資料的寫入時,對資料加上排他鎖。排他鎖只可以加一個,他和其他的排他鎖,共享鎖都相斥。
用上面的例子來說就是使用者的行為有兩種,一種是來看房,多個使用者一起看房是可以接受的。一種是真正的入住一晚,在這期間,無論是想入住的還是想看房的都不可以。
鎖的粒度取決於具體的儲存引擎,InnoDB實現了行級鎖,頁級鎖,表級鎖。
他們的加鎖開銷從大到小,併發能力也是從大到小。
5. MySQL中InnoDB引擎的行鎖是怎麼實現的?
答:InnoDB是基於索引來完成行鎖
例: select * from tab_with_index where id = 1 for update;
for update 可以根據條件來完成行鎖鎖定,並且 id 是有索引鍵的列,如果 id 不是索引鍵那麼InnoDB將完成表鎖,併發將無從談起
6. InnoDB儲存引擎的鎖的演算法有三種
- Record lock:單個行記錄上的鎖
- Gap lock:間隙鎖,鎖定一個範圍,不包括記錄本身
- Next-key lock:record+gap 鎖定一個範圍,包含記錄本身
相關知識點:
- innodb對於行的查詢使用next-key lock
- Next-locking keying為了解決Phantom Problem幻讀問題
- 當查詢的索引含有唯一屬性時,將next-key lock降級為record key
- Gap鎖設計的目的是為了阻止多個事務將記錄插入到同一範圍內,而這會導致幻讀問題的產生
- 有兩種方式顯式關閉gap鎖:(除了外來鍵約束和唯一性檢查外,其餘情況僅使用record lock) A. 將事務隔離級別設定為RC B. 將引數innodb_locks_unsafe_for_binlog設定為1
7. 什麼是死鎖?怎麼解決?
死鎖是指兩個或多個事務在同一資源上相互佔用,並請求鎖定對方的資源,從而導致惡性迴圈的現象。
常見的解決死鎖的方法
1、如果不同程式會併發存取多個表,儘量約定以相同的順序訪問表,可以大大降低死鎖機會。
2、在同一個事務中,儘可能做到一次鎖定所需要的所有資源,減少死鎖產生概率;
3、對於非常容易產生死鎖的業務部分,可以嘗試使用升級鎖定顆粒度,通過表級鎖定來減少死鎖產生的概率;
如果業務處理不好可以用分散式事務鎖或者使用樂觀鎖
8. 資料庫的樂觀鎖和悲觀鎖是什麼?怎麼實現的?
資料庫管理系統(DBMS)中的併發控制的任務是確保在多個事務同時存取資料庫中同一資料時不破壞事務的隔離性和統一性以及資料庫的統一性。樂觀併發控制(樂觀鎖)和悲觀併發控制(悲觀鎖)是併發控制主要採用的技術手段。
悲觀鎖:假定會發生併發衝突,遮蔽一切可能違反資料完整性的操作。在查詢完資料的時候就把事務鎖起來,直到提交事務。實現方式:使用資料庫中的鎖機制
樂觀鎖:假設不會發生併發衝突,只在提交操作時檢查是否違反資料完整性。在修改資料的時候把事務鎖起來,通過version的方式來進行鎖定。實現方式:樂一般會使用版本號機制或CAS演算法實現。
兩種鎖的使用場景
從上面對兩種鎖的介紹,我們知道兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下(多讀場景),即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。
但如果是多寫的情況,一般會經常產生衝突,這就會導致上層應用會不斷的進行retry,這樣反倒是降低了效能,所以一般多寫的場景下用悲觀鎖就比較合適。
檢視
1. 為什麼要使用檢視?什麼是檢視?
為了提高複雜SQL語句的複用性和表操作的安全性,MySQL資料庫管理系統提供了檢視特性。所謂檢視,本質上是一種虛擬表,在物理上是不存在的,其內容與真實的表相似,包含一系列帶有名稱的列和行資料。但是,檢視並不在資料庫中以儲存的資料值形式存在。行和列資料來自定義檢視的查詢所引用基本表,並且在具體引用檢視時動態生成。
檢視使開發者只關心感興趣的某些特定資料和所負責的特定任務,只能看到檢視中所定義的資料,而不是檢視所引用表中的資料,從而提高了資料庫中資料的安全性。
2. 檢視有哪些特點?
檢視的特點如下:
- 檢視的列可以來自不同的表,是表的抽象和在邏輯意義上建立的新關係。
- 檢視是由基本表(實表)產生的表(虛表)。
- 檢視的建立和刪除不影響基本表。
- 對檢視內容的更新(新增,刪除和修改)直接影響基本表。
- 當檢視來自多個基本表時,不允許新增和刪除資料。
檢視的操作包括建立檢視,檢視檢視,刪除檢視和修改檢視。
3. 檢視的使用場景有哪些?
檢視根本用途:簡化sql查詢,提高開發效率。如果說還有另外一個用途那就是相容老的表結構。
下面是檢視的常見使用場景:
- 重用SQL語句;
- 簡化複雜的SQL操作。在編寫查詢後,可以方便的重用它而不必知道它的基本查詢細節;
- 使用表的組成部分而不是整個表;
- 保護資料。可以給使用者授予表的特定部分的訪問許可權而不是整個表的訪問許可權;
- 更改資料格式和表示。檢視可返回與底層表的表示和格式不同的資料。
4. 檢視的優點
- 查詢簡單化。檢視能簡化使用者的操作
- 資料安全性。檢視使使用者能以多種角度看待同一資料,能夠對機密資料提供安全保護
- 邏輯資料獨立性。檢視對重構資料庫提供了一定程度的邏輯獨立性
5. 檢視的缺點
- 效能。資料庫必須把檢視的查詢轉化成對基本表的查詢,如果這個檢視是由一個複雜的多表查詢所定義,那麼,即使是檢視的一個簡單查詢,資料庫也把它變成一個複雜的結合體,需要花費一定的時間。
- 修改限制。當用戶試圖修改檢視的某些行時,資料庫必須把它轉化為對基本表的某些行的修改。事實上,當從檢視中插入或者刪除時,情況也是這樣。對於簡單檢視來說,這是很方便的,但是,對於比較複雜的檢視,可能是不可修改的 這些檢視有如下特徵:1.有UNIQUE等集合操作符的檢視。2.有GROUP BY子句的檢視。3.有諸如AVG\SUM\MAX等聚合函式的檢視。4.使用DISTINCT關鍵字的檢視。5.連線表的檢視(其中有些例外)
6. 什麼是遊標?
遊標是系統為使用者開設的一個數據緩衝區,存放SQL語句的執行結果,每個遊標區都有一個名字。使用者可以通過遊標逐一獲取記錄並賦給主變數,交由主語言進一步處理。
儲存過程與函式
什麼是儲存過程?有哪些優缺點?
儲存過程是一個預編譯的SQL語句,優點是允許模組化的設計,就是說只需要建立一次,以後在該程式中就可以呼叫多次。如果某次操作需要執行多次SQL,使用儲存過程比單純SQL語句執行要快。
優點
1)儲存過程是預編譯過的,執行效率高。
2)儲存過程的程式碼直接存放於資料庫中,通過儲存過程名直接呼叫,減少網路通訊。
3)安全性高,執行儲存過程需要有一定許可權的使用者。
4)儲存過程可以重複使用,減少資料庫開發人員的工作量。
缺點
1)除錯麻煩,但是用 PL/SQL Developer 除錯很方便!彌補這個缺點。
2)移植問題,資料庫端程式碼當然是與資料庫相關的。但是如果是做工程型專案,基本不存在移植問題。
3)重新編譯問題,因為後端程式碼是執行前編譯的,如果帶有引用關係的物件發生改變時,受影響的儲存過程、包將需要重新編譯(不過也可以設定成執行時刻自動編譯)。
4)如果在一個程式系統中大量的使用儲存過程,到程式交付使用的時候隨著使用者需求的增加會導致資料結構的變化,接著就是系統的相關問題了,最後如果使用者想維護該系統可以說是很難很難、而且代價是空前的,維護起來更麻煩。
觸發器
1. 什麼是觸發器?觸發器的使用場景有哪些?
觸發器是使用者定義在關係表上的一類由事件驅動的特殊的儲存過程。觸發器是指一段程式碼,當觸發某個事件時,自動執行這些程式碼。
使用場景
- 可以通過資料庫中的相關表實現級聯更改。
- 實時監控某張表中的某個欄位的更改而需要做出相應的處理。
- 例如可以生成某些業務的編號。
- 注意不要濫用,否則會造成資料庫及應用程式的維護困難。
- 大家需要牢記以上基礎知識點,重點是理解資料型別CHAR和VARCHAR的差異,表儲存引擎InnoDB和MyISAM的區別。
2. MySQL中都有哪些觸發器?
在MySQL資料庫中有如下六種觸發器:
- Before Insert
- After Insert
- Before Update
- After Update
- Before Delete
- After Delete
常用SQL語句
1. SQL語句主要分為哪幾類
資料定義語言DDL(Data Ddefinition Language)CREATE,DROP,ALTER
主要為以上操作 即對邏輯結構等有操作的,其中包括表結構,檢視和索引。
資料查詢語言DQL(Data Query Language)SELECT
這個較為好理解 即查詢操作,以select關鍵字。各種簡單查詢,連線查詢等 都屬於DQL。
資料操縱語言DML(Data Manipulation Language)INSERT,UPDATE,DELETE
主要為以上操作 即對資料進行操作的,對應上面所說的查詢操作 DQL與DML共同構建了多數初級程式設計師常用的增刪改查操作。而查詢是較為特殊的一種 被劃分到DQL中。
資料控制功能DCL(Data Control Language)GRANT,REVOKE,COMMIT,ROLLBACK
主要為以上操作 即對資料庫安全性完整性等有操作的,可以簡單的理解為許可權控制等。
2. 超鍵、候選鍵、主鍵、外來鍵分別是什麼?
- 超鍵:在關係中能唯一標識元組的屬性集稱為關係模式的超鍵。一個屬性可以為作為一個超鍵,多個屬性組合在一起也可以作為一個超鍵。超鍵包含候選鍵和主鍵。
- 候選鍵:是最小超鍵,即沒有冗餘元素的超鍵。
- 主鍵:資料庫表中對儲存資料物件予以唯一和完整標識的資料列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能為空值(Null)。
- 外來鍵:在一個表中存在的另一個表的主鍵稱此表的外來鍵。
3. SQL 約束有哪幾種?
SQL 約束有哪幾種?
- NOT NULL: 用於控制欄位的內容一定不能為空(NULL)。
- UNIQUE: 控制元件欄位內容不能重複,一個表允許有多個 Unique 約束。
- PRIMARY KEY: 也是用於控制元件欄位內容不能重複,但它在一個表只允許出現一個。
- FOREIGN KEY: 用於預防破壞表之間連線的動作,也能防止非法資料插入外來鍵列,因為它必須是它指向的那個表中的值之一。
- CHECK: 用於控制欄位的值範圍。
4. 六種關聯查詢
- 交叉連線(CROSS JOIN)
- 內連線(INNER JOIN)
- 外連線(LEFT JOIN/RIGHT JOIN)
- 聯合查詢(UNION與UNION ALL)
- 全連線(FULL JOIN)
- 交叉連線(CROSS JOIN)
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
內連線分為三類
- 等值連線:ON A.id=B.id
- 不等值連線:ON A.id > B.id
- 自連線:SELECT * FROM A T1 INNER JOIN A T2 ON T1.id=T2.pid
外連線(LEFT JOIN/RIGHT JOIN)
- 左外連線:LEFT OUTER JOIN, 以左表為主,先查詢出左表,按照ON後的關聯條件匹配右表,沒有匹配到的用NULL填充,可以簡寫成LEFT JOIN
- 右外連線:RIGHT OUTER JOIN, 以右表為主,先查詢出右表,按照ON後的關聯條件匹配左表,沒有匹配到的用NULL填充,可以簡寫成RIGHT JOIN
聯合查詢(UNION與UNION ALL)
SELECT * FROM A UNION SELECT * FROM B UNION ...
- 就是把多個結果集集中在一起,UNION前的結果為基準,需要注意的是聯合查詢的列數要相等,相同的記錄行會合並
- 如果使用UNION ALL,不會合並重復的記錄行
- 效率 UNION 高於 UNION ALL
全連線(FULL JOIN)
- MySQL不支援全連線
- 可以使用LEFT JOIN 和UNION和RIGHT JOIN聯合使用
SELECT * FROM A LEFT JOIN B ON A.id=B.id UNIONSELECT * FROM A RIGHT JOIN B ON A.id=B.id
表連接面試題
有2張表,1張R、1張S,R表有ABC三列,S表有CD兩列,表中各有三條記錄。
R表
A | B | C |
---|---|---|
a1 | b1 | c1 |
a2 | b2 | c2 |
a3 | b3 | c3 |
S表
C | D |
---|---|
c1 | d1 |
c2 | d2 |
c4 | d3 |
- 交叉連線(笛卡爾積):
select r.,s. from r,s
A | B | C | C | D |
---|---|---|---|---|
a1 | b1 | c1 | c1 | d1 |
a2 | b2 | c2 | c1 | d1 |
a3 | b3 | c3 | c1 | d1 |
a1 | b1 | c1 | c2 | d2 |
a2 | b2 | c2 | c2 | d2 |
a3 | b3 | c3 | c2 | d2 |
a1 | b1 | c1 | c4 | d3 |
a2 | b2 | c2 | c4 | d3 |
a3 | b3 | c3 | c4 | d3 |
2.內連線結果:
select r.,s. from r inner join s on r.c=s.c
A | B | C | C | D |
---|---|---|---|---|
a1 | b1 | c1 | c1 | d1 |
a2 | b2 | c2 | c2 | d2 |
3.左連線結果: