一個典型的互聯網產品架構包含接入層、邏輯處理層以及存儲層,其中存儲層承載着數據落地和持久化的任務,同時給邏輯處理層提供數據查詢功能支持。說到存儲層就要說到數據庫,數據庫知識掌握程度也是面試考察的知識點。python
數據庫分爲關係型數據庫和非關係型數據庫,也就是咱們常說的 SQL 和 NoSQL,這兩個方向的數據庫表明產品分別是MySQL 和 Redis ,此次咱們主要以面試問答的形式,來學習下關係型數據庫 MySQL 基礎知識。mysql
面試開始,準備接受面試官靈魂拷問吧!面試
關係型數據庫,是指採用了關係模型來組織數據的數據庫,其以行和列的形式存儲數據,以便於用戶理解,關係型數據庫這一系列的行和列被稱爲表,一組表組成了數據庫。 用戶經過查詢來檢索數據庫中的數據,而查詢是一個用於限定數據庫中某些區域的執行代碼。算法
簡單來講,關係模式就是二維表格模型。
sql
關係型數據庫的優點:數據庫
易於理解編程
關係型二維表的結構很是貼近現實世界,二維表格,容易理解。緩存
支持複雜查詢
能夠用 SQL 語句方便的在一個表以及多個表之間作很是複雜的數據查詢。安全
支持事務
可靠的處理事務而且保持事務的完整性,使得對於安全性能很高的數據訪問要求得以實現。服務器
結構化查詢語言 (Structured Query Language) 簡稱SQL,是一種特殊目的的編程語言,是一種數據庫查詢和程序設計語言程序設計語言,用於存取數據以及查詢、更新和管理關係數據庫系統。
MySQL 是一個關係型數據庫管理系統,MySQL 是最流行的關係型數據庫管理系統之一,常見的關係型數據庫還有 Oracle 、SQL Server、Access 等等。
MySQL在過去因爲性能高、成本低、可靠性好,已經成爲最流行的開源數據庫,普遍地應用在 Internet 上的中小型網站中。
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 -V
鏈接上MySQL命令行輸入:
> status
;
Server: MySQL
Server version: 5.5.45
Protocol version: 10
複製代碼
或 select version();
+------------------------+
| version() |
+------------------------+
| 5.5.45-xxxxx |
+------------------------+
複製代碼
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 個字符,注意不是字節!!
CHAR(M)
若是實際存儲的數據長度小於M,則 MySQL 會自動會在它的右邊用空格字符補足,可是在檢索操做中那些填補出來的空格字符會被去掉。存放的漢字個數與版本相關。
mysql 4.0如下版本,varchar(50) 指的是 50 字節,若是存放 UTF8 格式編碼的漢字時(每一個漢字3字節),只能存放16 個。
mysql 5.0以上版本,varchar(50) 指的是 50 字符,不管存放的是數字、字母仍是 UTF8 編碼的漢字,均可以存放 50 個。
不同,具體緣由以下:
因此能存儲的數據大小不同,其中的數字 10
表明的只是數據的顯示寬度。[^13]
zerofill
選項,則不足顯示寬度的部分用 0
填充,若是是 1 會顯示成 0000000001
。經常使用的存儲引擎有 InnoDB 存儲引擎和 MyISAM 存儲引擎,InnoDB 是 MySQL 的默認事務引擎。
查看數據庫表當前支持的引擎,能夠用下面查詢語句查看 :
# 查詢結果表中的 Engine 字段指示存儲引擎類型。
show table status from 'your_db_name' where name='your_table_name';
複製代碼
InnoDB 是 MySQL的默認「事務引擎」,被設置用來處理大量短時間(short-lived)事務,短時間事務大部分狀況是正常提交的,不多會回滾。
採用多版本併發控制(MVCC,MultiVersion Concurrency Control)來支持高併發。而且實現了四個標準的隔離級別,經過間隙鎖next-key locking
策略防止幻讀的出現。
引擎的表基於聚簇索引創建,聚簇索引對主鍵查詢有很高的性能。不過它的二級索引secondary index
非主鍵索引中必須包含主鍵列,因此若是主鍵列很大的話,其餘的全部索引都會很大。所以,若表上的索引較多的話,主鍵應當儘量的小。另外InnoDB的存儲格式是平臺獨立。
InnoDB作了不少優化,好比:磁盤讀取數據方式採用的可預測性預讀、自動在內存中建立hash索引以加速讀操做的自適應哈希索引(adaptive hash index),以及可以加速插入操做的插入緩衝區(insert buffer)等。
InnoDB經過一些機制和工具支持真正的熱備份,MySQL 的其餘存儲引擎不支持熱備份,要獲取一致性視圖須要中止對全部表的寫入,而在讀寫混合場景中,中止寫入可能也意味着中止讀取。
Insert Buffer 用於非彙集索引的插入和更新操做。先判斷插入的非彙集索引是否在緩存池中,若是在則直接插入,不然插入到 Insert Buffer 對象裏。再以必定的頻率進行 Insert Buffer 和輔助索引葉子節點的 merge 操做,將屢次插入合併到一個操做中,提升對非彙集索引的插入性能。
Double Write由兩部分組成,一部分是內存中的double write buffer,大小爲2MB,另外一部分是物理磁盤上共享表空間連續的128個頁,大小也爲 2MB。在對緩衝池的髒頁進行刷新時,並不直接寫磁盤,而是經過 memcpy 函數將髒頁先複製到內存中的該區域,以後經過doublewrite buffer再分兩次,每次1MB順序地寫入共享表空間的物理磁盤上,而後立刻調用fsync函數,同步磁盤,避免操做系統緩衝寫帶來的問題。
InnoDB會根據訪問的頻率和模式,爲熱點頁創建哈希索引,來提升查詢效率。索引經過緩存池的 B+ 樹頁構造而來,所以創建速度很快,InnoDB存儲引擎會監控對錶上各個索引頁的查詢,若是觀察到創建哈希索引能夠帶來速度上的提高,則創建哈希索引,因此叫作自適應哈希索引。
爲了提升數據庫的性能,引入緩存池的概念,經過參數 innodb_buffer_pool_size 能夠設置緩存池的大小,參數 innodb_buffer_pool_instances 能夠設置緩存池的實例個數。緩存池主要用於存儲如下內容:
緩衝池中緩存的數據頁類型有:索引頁、數據頁、undo頁、插入緩衝 (insert buffer)、自適應哈希索引(adaptive hash index)、InnoDB存儲的鎖信息 (lock info)和數據字典信息 (data dictionary)。
MyISAM 是 MySQL 5.1 及以前的版本的默認的存儲引擎。MyISAM 提供了大量的特性,包括全文索引、壓縮、空間函數(GIS)等,但MyISAM 不「支持事務和行級鎖」,對於只讀數據,或者表比較小、能夠容忍修復操做,依然可使用它。
MyISAM「不支持行級鎖而是對整張表加鎖」。讀取時會對須要讀到的全部表加共享鎖,寫入時則對錶加排它鎖。但在表有讀取操做的同時,也能夠往表中插入新的記錄,這被稱爲併發插入。
MyISAM 表能夠手工或者自動執行檢查和修復操做。可是和事務恢復以及崩潰恢復不一樣,可能致使一些「數據丟失」,並且修復操做是很是慢的。
對於 MyISAM 表,即便是BLOB
和TEXT
等長字段,也能夠基於其前 500 個字符建立索引,MyISAM 也支持「全文索引」,這是一種基於分詞建立的索引,能夠支持複雜的查詢。
若是指定了DELAY_KEY_WRITE
選項,在每次修改執行完成時,不會當即將修改的索引數據寫入磁盤,而是會寫到內存中的鍵緩衝區,只有在清理鍵緩衝區或者關閉表的時候纔會將對應的索引塊寫入磁盤。這種方式能夠極大的提高寫入性能,可是在數據庫或者主機崩潰時會形成「索引損壞」,須要執行修復操做。
SELECT COUNT(*)
經常使用於統計表的總行數,在 MyISAM 存儲引擎中執行更快,前提是不能加有任何WHERE條件。
這是由於 MyISAM 對於表的行數作了優化,內部用一個變量存儲了表的行數,若是查詢條件沒有 WHERE 條件則是查詢表中一共有多少條數據,MyISAM 能夠迅速返回結果,若是加 WHERE 條件就不行。
InnoDB 的表也有一個存儲了錶行數的變量,但這個值是一個估計值,因此並無太大實際意義。
1範式:1NF是對屬性的原子性約束,要求屬性具備原子性,不可再分解;(只要是關係型數據庫都知足1NF)
2範式:2NF是對記錄的唯一性約束,要求記錄有唯一標識,即實體的唯一性;
3範式:3NF是對字段冗餘性的約束,即任何字段不能由其餘字段派生出來,它要求字段沒有冗餘。沒有冗餘的數據庫設計能夠作到
可是,沒有冗餘的數據庫未必是最好的數據庫,有時爲了提升運行效率,就必須下降範式標準,適當保留冗餘數據,具體作法是:在概念數據模型設計時遵照第三範式,下降範式標準的工做放到物理數據模型設計時考慮,下降範式就是增長字段,容許冗餘。
視圖是虛擬表,並不儲存數據,只包含定義時的語句的動態數據。
建立視圖語法:
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。
操做簡單方便。視圖用戶徹底不須要關心視圖對應的表的結構、關聯條件和篩選條件,對用戶來講已是過濾好的複合條件的結果集。
數據更加安全。視圖用戶只能訪問視圖中的結果集,經過視圖能夠把對錶的訪問權限限制在某些行和列上面。
數據隔離。屏蔽了源表結構變化對用戶帶來的影響,源表結構變化視圖結構不變。[^1]
默認端口是 3306
查看端口命令:> show variables like 'port';
DISTINCT 用於對選擇的數據去重,單列用法容易理解。好比有以下數據表 tamb
:
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 調用。
最後,小編想說:我是一名python開發工程師, 整理了一套最新的python系統學習教程, 想要這些資料的能夠關注私信小編「01」便可(免費分享哦)但願能對你有所幫助.