數據庫分爲關係型數據庫和非關係型數據庫
,也就是咱們常說的 SQL 和 NoSQL,這兩個方向的數據庫表明產品分別是MySQL 和 Redis ,此次咱們主要以面試問答的形式,來學習下關係型數據庫 MySQL 基礎知識。
關係型數據庫
什麼是關係型數據庫?
關係型數據庫,是指採用了關係模型來組織數據的數據庫,其以行和列的形式存儲數據,以便於用戶理解,關係型數據庫這一系列的行和列被稱爲表,一組表組成了數據庫。用戶經過查詢來檢索數據庫中的數據,而查詢是一個用於限定數據庫中某些區域的執行代碼。
簡單來講,關係模式就是二維表格模型。
關係型數據庫有什麼優點?
關係型數據庫的優點:
- 易於理解
關係型二維表的結構很是貼近現實世界,二維表格,容易理解。
- 支持複雜查詢 能夠用 SQL 語句方便的在一個表以及多個表之間作很是複雜的數據查詢。
- 支持事務 可靠的處理事務而且保持事務的完整性,使得對於安全性能很高的數據訪問要求得以實現。
MySQL數據庫
什麼是SQL
結構化查詢語言 (Structured Query Language) 簡稱SQL,是一種特殊目的的編程語言,是一種數據庫查詢和程序設計語言程序設計語言,用於存取數據以及查詢、更新和管理關係數據庫系統。
什麼是MySQL?
MySQL 是一個關係型數據庫管理系統,MySQL 是最流行的關係型數據庫管理系統之一,常見的關係型數據庫還有 Oracle 、SQL Server、Access 等等。
MySQL在過去因爲性能高、成本低、可靠性好,已經成爲最流行的開源數據庫,普遍地應用在 Internet 上的中小型網站中
。
MySQL 和 MariaDB 傻傻分不清楚?
MySQL 最初由瑞典 MySQL AB 公司開發,MySQL 的創始人是烏爾夫·米卡埃爾·維德紐斯,經常使用暱稱蒙提(Monty)。
在被甲骨文公司收購後,如今屬於甲骨文公司(Oracle) 旗下產品。Oracle 大幅調漲MySQL商業版的售價,所以致使自由軟件社區們對於Oracle是否還會持續支持MySQL社區版有所隱憂。
MySQL 的創始人就是以前那個叫 Monty 的大佬以 MySQL爲基礎成立分支計劃 MariaDB。
MariaDB打算保持與MySQL的高度兼容性,確保具備庫二進制奇偶校驗的直接替換功能,以及與MySQL API 應用程序接口)和命令的精確匹配。而原先一些使用 MySQL 的開源軟件逐漸轉向 MariaDB 或其它的數據庫。
因此若是看到你公司用的是 MariaDB 不用懷疑,其實它骨子裏仍是 MySQL,學會了MySQL 也就會了 MariaDB。
一個彩蛋
MariaDB 是以 Monty 的小女兒Maria命名的,就像MySQL是以他另外一個女兒 My 命名的同樣,兩款鼎鼎大名的數據庫分別用兩個女兒的名字命名,你大爺仍是你大爺,老爺子牛批!
如何查看MySQL當前版本號?
在系統命令行下:mysql -V
鏈接上MySQL命令行輸入:
> status; Server: MySQL Server version: 5.5.45 Protocol version: 10 或 select version(); +------------------------+ | version() | +------------------------+ | 5.5.45-xxxxx | +------------------------+
基礎數據類型mysql
MySQL 有哪些數據類型?
MySQL 數據類型很是豐富,經常使用類型簡單介紹以下:
整數類型:BIT、BOOL、TINY INT、SMALL INT、MEDIUM INT、 INT、 BIG INT
浮點數類型:FLOAT、DOUBLE、DECIMAL
字符串類型:CHAR、VARCHAR、TINY TEXT、TEXT、MEDIUM TEXT、LONGTEXT、TINY BLOB、BLOB、MEDIUM BLOB、LONG BLOB
日期類型:Date、DateTime、TimeStamp、Time、Year
其餘數據類型:BINARY、VARBINARY、ENUM、SET...
CHAR 是固定長度的字符類型,VARCHAR 則是可變長度的字符類型
,下面討論基於在 MySQL5.0 以上版本中。
共同點
CHAR(M) 和 VARCHAR(M) 都表示該列能存儲 M 個
字符
,
注意不是字節!!
HAR類型特色
- CHAR 最多能夠存儲 255 個字符 (注意不是字節),字符有不一樣的編碼集,好比 UTF8 編碼 (3字節)、GBK 編碼 (2字節) 等。
- 對於 CHAR(M) 若是實際存儲的數據長度小於M,則 MySQL 會自動會在它的右邊用空格字符補足,可是在檢索操做中那些填補出來的空格字符會被去掉。
VARCHAR類型特色
- VARCHAR 的最大長度爲 65535 個字符。
- VARCHAR 存儲的是實際的字符串加1或2個字節用來記錄字符串實際長度,字符串長度小於255字節用1字節記錄,超過255就須要2字節記錄。[^12 ]
VARCHAR(50) 能存放幾個 UTF8 編碼的漢字?
存放的漢字個數與版本相關。
mysql 4.0如下版本,varchar(50) 指的是 50
字節
,若是存放 UTF8 格式編碼的漢字時(每一個漢字3字節),只能存放16 個。
mysql 5.0以上版本,varchar(50) 指的是 50
字符
,不管存放的是數字、字母仍是 UTF8 編碼的漢字,均可以存放 50 個。
int(10) 和 bigint(10)能存儲的數據大小同樣嗎?
不同,具體緣由以下:
- int 能存儲四字節有符號整數。
- bigint 能存儲八字節有符號整數。
因此能存儲的數據大小不同,其中的數字 10
表明的只是數據的顯示寬度。[^13]
- 顯示寬度指明Mysql最大可能顯示的數字個數,數值的位數小於指定的寬度時數字左邊會用空格填充,空格不容易看出。
- 若是插入了大於顯示寬度的值,只要該值不超過該類型的取值範圍,數值依然能夠插入且可以顯示出來。
- 建表的時候指定 zerofill 選項,則不足顯示寬度的部分用 0 填充,若是是 1 會顯示成 0000000001。
- 若是沒指定顯示寬度, bigint 默認寬度是 20 ,int默認寬度 11。
存儲引擎相關
MySQL存儲引擎類型有哪些?
經常使用的存儲引擎有 InnoDB 存儲引擎和 MyISAM 存儲引擎,InnoDB 是 MySQL 的默認事務引擎。
查看數據庫表當前支持的引擎,能夠用下面查詢語句查看 :
# 查詢結果表中的 Engine 字段指示存儲引擎類型。
show table status from 'your_db_name' where name='your_table_name';
InnoDB存儲引擎應用場景是什麼?面試
InnoDB 是 MySQL的默認「事務引擎」,被設置用來處理大量短時間(short-lived)事務,短時間事務大部分狀況是正常提交的,不多會回滾。
InnoDB存儲引擎特性有哪些?
採用多版本併發控制(MVCC,MultiVersion Concurrency Control)來支持高併發。
而且實現了
四個標準的隔離級別
,經過間隙鎖next-key locking
策略防止幻讀的出現。
引擎的表基於聚簇索引創建,聚簇索引對主鍵查詢有很高的性能。不過它的二級索引secondary index
非主鍵索引中必須包含主鍵列,因此若是主鍵列很大的話,其餘的全部索引都會很大。所以,若表上的索引較多的話,主鍵應當儘量的小。另外InnoDB的存儲格式是平臺獨立。
InnoDB作了不少優化,好比:磁盤讀取數據方式採用的可預測性預讀、自動在內存中建立hash索引以加速讀操做的自適應哈希索引(adaptive hash index),以及可以加速插入操做的插入緩衝區(insert buffer)等。
InnoDB經過一些機制和工具支持真正的熱備份,MySQL 的其餘存儲引擎不支持熱備份,要獲取一致性視圖須要中止對全部表的寫入,而在讀寫混合場景中,中止寫入可能也意味着中止讀取。
四個隔離級別
InnoDB 引擎的四大特性是什麼?
插入緩衝(Insert buffer)
Insert Buffer 用於非彙集索引的插入和更新操做。先判斷插入的非彙集索引是否在緩存池中,若是在則直接插入,不然插入到 Insert Buffer 對象裏。再以必定的頻率進行 Insert Buffer 和輔助索引葉子節點的 merge 操做,將屢次插入合併到一個操做中,提升對非彙集索引的插入性能。
二次寫 (Double write)
Double Write由兩部分組成,一部分是內存中的double write buffer,大小爲2MB,另外一部分是物理磁盤上共享表空間連續的128個頁,大小也爲 2MB。在對緩衝池的髒頁進行刷新時,並不直接寫磁盤,而是經過 memcpy 函數將髒頁先複製到內存中的該區域,以後經過doublewrite buffer再分兩次,每次1MB順序地寫入共享表空間的物理磁盤上,而後立刻調用fsync函數,同步磁盤,避免操做系統緩衝寫帶來的問題。
自適應哈希索引 (Adaptive Hash Index)
InnoDB會根據訪問的頻率和模式,爲熱點頁創建哈希索引,來提升查詢效率。索引經過緩存池的 B+ 樹頁構造而來,所以創建速度很快,InnoDB存儲引擎會監控對錶上各個索引頁的查詢,若是觀察到創建哈希索引能夠帶來速度上的提高,則創建哈希索引,因此叫作自適應哈希索引。
緩存池
爲了提升數據庫的性能,引入緩存池的概念,經過參數 innodb_buffer_pool_size 能夠設置緩存池的大小,參數 innodb_buffer_pool_instances 能夠設置緩存池的實例個數。緩存池主要用於存儲如下內容:
緩衝池中緩存的數據頁類型有:索引頁、數據頁、undo頁、插入緩衝 (insert buffer)、自適應哈希索引(adaptive hash index)、InnoDB存儲的鎖信息 (lock info)和數據字典信息 (data dictionary)
MyISAM存儲引擎應用場景有哪些?
MyISAM 是 MySQL 5.1 及以前的版本的默認的存儲引擎。MyISAM 提供了大量的特性,包括全文索引、壓縮、空間函數(GIS)等,但MyISAM 不「支持事務和行級鎖」,對於只讀數據,或者表比較小、能夠容忍修復操做,依然可使用它。
MyISAM存儲引擎特性有哪些?
MyISAM「不支持行級鎖而是對整張表加鎖」。讀取時會對須要讀到的全部表加共享鎖,寫入時則對錶加排它鎖。但在表有讀取操做的同時,也能夠往表中插入新的記錄,這被稱爲併發插入。
MyISAM 表能夠手工或者自動執行檢查和修復操做。可是和事務恢復以及崩潰恢復不一樣,可能致使一些「數據丟失」,並且修復操做是很是慢的。
對於 MyISAM 表,即便是BLOB
和TEXT
等長字段,也能夠基於其前 500 個字符建立索引,MyISAM 也支持「全文索引」,這是一種基於分詞建立的索引,能夠支持複雜的查詢。
若是指定了DELAY_KEY_WRITE
選項,在每次修改執行完成時,不會當即將修改的索引數據寫入磁盤,而是會寫到內存中的鍵緩衝區,只有在清理鍵緩衝區或者關閉表的時候纔會將對應的索引塊寫入磁盤。這種方式能夠極大的提高寫入性能,可是在數據庫或者主機崩潰時會形成「索引損壞」,須要執行修復操做。
MyISAM 與 InnoDB 存儲引擎 5 大區別
- InnoDB支持事物,而MyISAM不支持事物
- InnoDB支持行級鎖,而MyISAM支持表級鎖
- InnoDB支持MVCC, 而MyISAM不支持
- InnoDB支持外鍵,而MyISAM不支持
- InnoDB不支持全文索引,而MyISAM支持
一張表簡單羅列兩種引擎的主要區別,以下圖:

SELECT COUNT(*) 在哪一個引擎執行更快?
SELECT COUNT(*)
經常使用於統計表的總行數,
在 MyISAM 存儲引擎中執行更快,前提是不能加有任何WHERE條件
。
這是由於 MyISAM 對於表的行數作了優化,內部用一個變量存儲了表的行數,若是查詢條件沒有 WHERE 條件則是查詢表中一共有多少條數據,MyISAM 能夠迅速返回結果,若是加 WHERE 條件就不行。
InnoDB 的表也有一個存儲了錶行數的變量,但這個值是一個估計值,因此並無太大實際意義。
MySQL 基礎知識
說一下數據庫設計三範式是什麼?
1範式:1NF是對屬性的原子性約束,要求屬性具備原子性,不可再分解;(只要是關係型數據庫都知足1NF)
2範式:2NF是對記錄的唯一性約束,要求記錄有唯一標識,即實體的唯一性;
3範式:3NF是對字段冗餘性的約束,即任何字段不能由其餘字段派生出來,它要求字段沒有冗餘。沒有冗餘的數據庫設計能夠作到
可是,沒有冗餘的數據庫未必是最好的數據庫,有時爲了提升運行效率,就必須下降範式標準,適當保留冗餘數據,具體作法是:在概念數據模型設計時遵照第三範式,下降範式標準的工做放到物理數據模型設計時考慮,下降範式就是增長字段,容許冗餘。
SQL 語句有哪些分類?
- DDL:數據定義語言(create alter drop)
- DML:數據操做語句(insert update delete)
- DTL:數據事務語句(commit rollback savapoint)
- DCL:數據控制語句(grant revoke)
數據庫刪除操做中的 delete、drop、 truncate 區別在哪?
- 當再也不須要該表時能夠用 drop 來刪除表;
- 當仍要保留該表,但要刪除全部記錄時, 用 truncate來刪除表中記錄。
- 當要刪除部分記錄時(通常來講有 WHERE 子句約束) 用 delete來刪除表中部分記錄。
什麼是MySql視圖?
視圖是虛擬表,並不儲存數據,只包含定義時的語句的動態數據。
建立視圖語法:
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = user] [SQL SECURITY { DEFINER | INVOKER }] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
參數說明:算法
- OR REPLACE:若是視圖存在,則替換已有視圖。
- ALGORITHM:視圖選擇算法,默認算法是 UNDEFINED(未定義的)由 MySQL自動選擇要使用的算法。
- DEFINER:指定視圖建立者或定義者,若是不指定該選項,則建立視圖的用戶就是定義者。
- SQL SECURITY:SQL安全性,默認爲DEFINER。
- select_statement:建立視圖的 SELECT語句,能夠從基表或其餘視圖中選擇數據。
- WITH CHECK OPTION:表示視圖在更新時保證約束,默認是 CASCADED。
使用 MySQL 視圖有何優勢?
- 操做簡單方便。視圖用戶徹底不須要關心視圖對應的表的結構、關聯條件和篩選條件,對用戶來講已是過濾好的複合條件的結果集。
- 數據更加安全。視圖用戶只能訪問視圖中的結果集,經過視圖能夠把對錶的訪問權限限制在某些行和列上面。
- 數據隔離。屏蔽了源表結構變化對用戶帶來的影響,源表結構變化視圖結構不變。
MySql服務默認端口號是多少 ?
默認端口是 3306 查看端口命令:
> show variables like 'port';
DISTINCT 用於對選擇的數據去重,單列用法容易理解。好比有以下數據表 tamb :sql
name number Tencent 1 Alibaba 2 Bytedance 3 Meituan 3
查詢語句:數據庫
SELECT DISTINCT name FROM table tamb 編程
結果以下:緩存
name Tencent Alibaba Bytedance Meituan
若是要求按 number 列去重同時顯示 name ,你可能會寫出查詢語句:安全
SELECT DISTINCT number, name FROM table tamb
多參數 DISTINCT 去重規則是:把 DISTINCT 以後的全部參數當作一個過濾條件,也就是說會對 (number, name) 總體去重處理,只有當這個組合相同纔會去重 ,結果以下:服務器
number name 1 Tencent 2 Alibaba 3 Bytedance 3 Meituan
從結果來看好像並無達到咱們想要的去重的效果,那要怎麼實現「按 number 列去重同時顯示 name 呢?能夠用 Group By 語句:網絡
SELECT number, name FROM table tamb GROUP BY number
輸出以下,正是咱們想要的效果:
number name 1 Tencent 2 Alibaba 3 Bytedance
什麼是存儲過程?
一條或多條sql語句集合,有如下一些特色:
- 存儲過程能實現較快的執行速度。
- 存儲過程能夠用流程控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。
- 存儲過程可被做爲一種安全機制來充分利用。
- 存儲過程可以減小網絡流量
delimiter 分隔符 create procedure|proc proc_name() begin sql語句 end 分隔符 delimiter ; --還原分隔符,爲了避免影響後面的語句的使用 --默認的分隔符是;可是爲了能在整個存儲過程當中重用,所以通常須要自定義分隔符(除\外) show procedure status like ""; --查詢存儲過程,能夠不適用like進行過濾 drop procedure if exists;--刪除存儲過程
存儲過程和函數好像差很少,你說說他們有什麼區別?
存儲過程和函數是事先通過編譯並存儲在數據庫中的一段 SQL 語句的集合,調用存儲過程和函數能夠簡化應用開發人員的不少工做,減小數據在數據庫和應用服務器之間的傳輸,對於提升數據處理的效率是有好處的。
相同點
- 存儲過程和函數都是爲了可重複的執行操做數據庫的 SQL 語句的集合。
- 存儲過程和函數都是一次編譯後緩存起來,下次使用就直接命中已經編譯好的 sql 語句,減小網絡交互提升了效率。
不一樣點
- 標識符不一樣,函數的標識符是 function,存儲過程是 procedure。
- 函數返回單個值或者表對象,而存儲過程沒有返回值,可是能夠經過OUT參數返回多個值。
- 函數限制比較多,好比不能用臨時表,只能用表變量,一些函數都不可用等,而存儲過程的限制相對就比較少。
- 通常來講,存儲過程實現的功能要複雜一點,而函數的實現的功能針對性比較強
- 函數的參數只能是 IN 類型,存儲過程的參數能夠是IN OUT INOUT三種類型。
- 存儲函數使用 select 調用,存儲過程須要使用 call 調用。