1. 程式人生 > >資料庫基礎知識整理與複習總結

資料庫基礎知識整理與複習總結

### 1、資料庫底層 MySQL資料庫的底層是B+樹。說到B+樹,先說下B樹,B樹也叫多路平衡查詢樹,所有的葉子節點位於同一層,具有以下特點:1)一個節點可以容納多個值;2)除非資料已滿,不會增加新的層,B樹追求最少的層數;3)子節點中的值與父節點的值有嚴格的大小對應關係。一般來說,如果父節點有a個值,那麼就有a+1個子節點;4)關鍵字集合分佈在整棵樹中;5)任何一個關鍵字出現且只出現在一個節點中;6)搜尋可能在葉子結點結束,其搜尋效能等價於在關鍵字全集做一次二分查詢。 B+樹是基於B樹和葉子節點順序訪問指標進行實現,它具有B樹的平衡性,並且通過順序訪問指標來提高區間查詢的效能,一個葉子節點中的key從左至右非遞減排列。特點在於:1)非葉子節點中含有n個關鍵字,關鍵字不儲存資料,只作為索引,所有資料都儲存在葉子結點;2)有的葉子節點中包含了全部關鍵字的資訊及只想這些關鍵字記錄的指標,即葉子節點包含連結串列結構,能夠方便進行區間查詢;3)所有的非葉子結點可以看成是索引部分,節點中僅包含其子樹中的最大(或最小)關鍵字;4)同一個數字會在不同節點中重複出現,根節點的最大元素就是B+樹的最大元素。 MySQL中的InnoDB引擎是以主鍵ID為索引的資料儲存引擎。InnoDB通過B+樹結構對ID建立索引,在葉子節點儲存資料。若建索引的欄位不是主鍵ID,則對該欄位建索引,然後再葉子節點中儲存的是該記錄的主鍵,然後通過主鍵索引找到對應的記錄。因為不再需要全表掃描,只需要對樹進行搜尋即可,所以查詢速度很快,還可以用於排序和分組。 InnoDB和MyISAM引擎都是基於B+樹,InnoDB是聚簇索引,資料域存放的是完整的資料記錄;MyISAM是非聚簇索引,資料域存放的是資料記錄的地址。InnoDB支援表鎖、行鎖、間隙鎖、外來鍵以及事務,MyISAM僅支援表鎖,同時不支援外來鍵和事務。InnoDB注重事務,MyISAM注重效能。 ### 2、SQL語言之DQL、DML、DDL和DCL DQL指的是Data Query Language,資料庫查詢語言,主要是select命令; DML指的是Data Manipulation Language,資料庫操作語言,主要有insert、delete、update等命令; DDL指的是Data Defined Language,資料庫定義語言,主要是對資料庫的某些物件,如database和table進行管理,主要有create、alter、drop等命令,比如建立資料庫和表格、更改表結構和設定約束、刪除表和資料庫; DCL指的是Data Control Language,資料庫控制語言,主要是用於授予或回收訪問資料庫的某種特權,並控制資料庫操縱事務發生的時間及效果,主要有grant、rollback等命令。 DML和DDL的區別:DML操作可以手動控制事務的開啟、提交和回滾,而DDL是隱形提交不能回滾。 ### 3、資料庫連線協議 JDBC驅動協議:預設TCP協議 客戶端和Oracle伺服器之間通訊協議是TCP的,但是一個數據庫連線也會其一個UDP埠。 MySQL的連線方式有兩種:Socket和TCP/IP ```mysql -- Socket連線方式 mysql -uroot -padmin -S/application/mysql/tmp/mysql.sock -- TCP/IP連線方式 mysql -uoot -padmin -h192.1.1.20 ``` ### 4、索引和主鍵的區別 主鍵用於標識資料庫記錄的唯一性,不允許記錄重複且鍵值不能為空。主鍵是特殊索引,但索引不一定是主鍵。 索引可以提高查詢速度,可以不需要進行全表掃描而快速查詢到結果。 使用主鍵,資料庫會自動建立主鍵索引,同時也可以再非主鍵上建立索引。 資料表中只能由一個主鍵,但可以有多個索引。 ### 5、資料庫四正規化 正規化:建立資料庫的過程中必須遵循的準則。其作用在於減少資料庫中的資料冗餘,以增加資料的一致性。 候選鍵:唯一識別該表的屬性或屬性表。 第一正規化(1NF):屬性不可拆分或無重複的列; 第二正規化(2NF):資料庫中的每一行必須被唯一地區分,即表中欄位必須完全依賴於全部主鍵而非部分主鍵; 第三正規化(3NF):消除傳遞依賴,資料庫非主鍵外的所有欄位僅能以來於候選鍵,不存在與其他非主鍵關聯; 第四正規化(4NF):一個表的主鍵只對應一個多值,即消除多值依賴。 ### 6、SQL基礎 資料庫的建立與使用: ```mysql create database test; use test; ``` 建立表: ```mysql create table mytable ( id int not null auto_increment, name varchar(20) ); ``` 修改表: ```mysql alter table mytable add sex varchar(20); ``` 增刪改: ```mysql insert into mytable(id,name,sex) values(1,'zhangsan','male'); delete from mytable where id = 1; update mytable set name = 'lisi' where id = 1; ``` 清空表: ```mysql truncate table mytable; ``` distinct:用於返回唯一不同的值 ```mysql select distinct name from mytable; ``` limit:檢索記錄行 ```mysql -- 檢索前5個記錄行 select * from mytable limit 5; -- 檢索記錄行1-5行 select * from mytable limit 0, 5; -- 檢索6-last行 select * from mytable limit 5, -1; ``` 排序: ```mysql -- 預設升序 select * from mytable order by col1 DESC, col2 ASC; ``` like匹配: ```mysql -- %匹配大於等於1個任意字元 select * from mytable where name = 'z%'; -- _匹配1個任意字元 select * from mytable where name = 'l_s_'; -- []匹配集合內的字元 select * from mytable where name = '[zl]%'; -- [!]匹配除開集合內的字元 select * from mytable where name = '[!z]%'; ``` concat():用於將多個字串連線成一個字串 ```mysql select concat(trim(col1), '(', trim(col2), ')') as new from mytable; ``` 函式: ```mysql -- 均值 select avg(col) as col_avg from mytable; -- 計數 select count(col) as col_count from mytable; -- 類似的sum()、max()、min()等 -- 時間 select now(); ``` 分組: ```mysql select col, count(*) as num from mytable where col > 2 group by col having by num > 2; ``` 子查詢中只能返回一個欄位的資料: ```mysql select * from mytable1 where col1 in (select col2 from mytable2); ``` 組合查詢: ```mysql select * from mytable where col = 1 union select col from mytable where col = 2; ``` 檢視: ```mysql create view as myview as select * from mytable where id > 2; ``` 儲存過程: ```mysql create procedure myprocedure(out ret int) begin ... end ``` ### 7、 刪除操作delete、truncate和drop delete:直接刪除表中的某一行資料,並且同時將該行的刪除操作作為事務記錄在日誌中儲存便於進行回滾,因此delete操作更加佔用資源,資料空間不釋放。delete可以對table和view物件進行操作。 ```mysql delete from mytable where id = 1; ``` truncate:一次性從資料表中刪除所有資料(釋放儲存表資料所用的資料頁來刪除資料),因此不能回滾,佔用資源更加少,速度更快。資料空間釋放後,表和索引所佔用的空間會回覆到初始大小。只能對沒有關聯檢視的table進行操作,對於外來鍵約束引用的表,不能使用truncate,需要使用delete。 ```mysql truncate mytable; ``` drop:刪除整個表,包括表的結構、資料、定義等。屬於永久抹去,空間會釋放,無法恢復,對table和view都能操作。 ```mysql drop mytable; ``` 總結: 在速度上,drop > truncate > delete; 在操作物件上,delete和drop可以對table和view操作,truncate只能對table操作; 在表和索引所佔空間上,delete操作不會減少表和索引佔用的空間,truncate操作後表和索引所佔用的空間會恢復至初始大小,drop將表所佔用的空間全部釋放; 在回滾上方面,delete操作為DML語句可以回滾,truncate和drop為DDL語句,隱式提交無法回滾; 在刪除限制上,delete可以操作帶有外來鍵約束引用的表,而truncate不可以; ### 8、char和varchar的區別 char的長度是不可變的,而varchar的長度是可變的。例如,建立表時定義一個char[10]和varchar[10],當存入一個字串`sql`時,char所佔的長度依然為10,除了字元`sql`外後面跟7個空格,而varchar所佔的長度變為字串的實際長度3。在取資料時,char型別的要用`trim()`函式去掉多餘的空格,而varchar型別不需要。 char型別的存取速度比varchar快得多,因為其長度固定方便儲存與查詢;但char型別會付出空間的代價,是以空間換時間來爭取高的時間效率,而varchar是以空間效率為首。 char對英文字元(ASCII)佔用1個位元組,對漢字佔用2個位元組;varchar對英文字元和漢字都是佔用2個位元組。 ### 9、 資料庫的冷備份與熱備份 冷備份(off,慢,時間點上恢復):需要資料庫正常關閉,會提供一個完整的資料庫;將關鍵性檔案拷貝到另外位置;對於備份資料庫資訊而言,冷備份是最快最安全的方法。 優點:易歸檔、能夠回覆到某個時間點; 缺點:資料庫必須處於關閉狀態; 熱備份(on,塊):資料庫執行的情況下,備份資料庫操作的sql語句,當資料庫發生問題時可以重新執行一遍備份的sql語句。 優點:備份時資料庫仍可以使用、快速恢復、屬於表或資料庫級別的備份,並且時間短 缺點:不能出錯 ### 10、資料庫的事務及ACID屬性 事務:邏輯上的一組操作,要麼都執行,要麼都不執行。 四大特性: A原子性:事務是最小的執行單位,不可分割,要麼全部執行,要麼都不執行; C一致性:事務執行前後,資料庫的資料保持一致,多個事務對同一資料讀取的結果是相同的; I隔離性:併發訪問資料庫時,事務之間互不打擾,各併發事務之間的資料庫是獨立的; D永續性:一個事務被提交之後,該事務對資料庫所做的改變是持久的,不會被回滾。 ### 11、併發事務的問題 髒讀:一個事務讀取到了另一個事務還未提交的修改資料,如果另一個事務進行了回滾,這個資料就是髒資料。 修改丟失:一個事務讀取資料並進行了修改,另一個事務頁讀取了該資料進行了修改,這樣第一個事務的修改結果就丟失了,也就是修改丟失問題。 不可重複讀:一個事務對同一資料進行多次修改,期間另一事務也讀取了該資料並進行了修改,這樣第一個事務讀取到的資料可能不一致,稱為不可重複讀。 幻讀:一個事務在讀取多行資料時,另一個併發事務插入了一些新資料,後續查詢中第一個事務會查詢到一些原本不存在的資料記錄,稱為幻讀。在`Mysql`中利用`MVCC`解決了`快照讀幻讀`,利用`間隙鎖`解決了`當前讀幻讀`。 ### 12、隔離級別 讀未提交:最低隔離級別,允許讀取尚未提交的資料變更,會導致髒讀、不可重複讀和幻讀; 讀已提交:允許讀取併發事務已經提交的資料,可以阻止髒讀,會導致不可重複讀和幻讀; 可重複讀:對同一欄位多次讀取的結果都是一樣的,可以阻止髒讀和不可重複讀,會導致幻讀; 序列化:最高隔離界別,可以阻止髒讀、不可重複讀和幻讀。 MySQL中InnoDB引擎預設支援的隔離級別是可重複讀,使用的是next-key Lock演算法,可以避免幻讀的產生,可以完全保證事務的隔離性要求 ### 13、多表查詢 一對多關係:從表使用主表的主鍵作為外來鍵;主表中有的資料,從表中可以沒有;主表必須有資料,才能向從表中新增資料;要先刪除從表的相應資料才能刪除主表的資料; 多對多關係:老師與學生,一個老師可以教多個學生,一個學生也可以從多個老師那裡學習知識。建立表格時,將多對多的關係拆分為多個一對多關係。 ### 14、資料庫表的連線方式 內連線:inner join……on…… :取交集 外連線: - 1)left join……on…… :以左表為準,查詢出左表的所有資料,右表中有對應的則顯示出來,沒有對應的則顯示為null; - 2)right join……on…… :以右表為準,查詢出右表的所有資料,左表中有對應的則顯示出來,沒有對應的則顯示為null; - 3)full join……on…… :left和right的集合,某表中某一行在另一表中無匹配行,則相應列的內容為null; 交叉連線:cross join…… :笛卡爾積,相當於兩個表中的所有行進行排列組合。 ### 15、儲存過程與儲存函式 儲存過程:為以後的使用而儲存的一條或多條SQL語句的集合,相當於批處理。儲存過程被編譯後會被直接儲存在資料庫中,成為資料庫的一部分,以後就可以反覆呼叫、執行速度快。 ```mysql -- in表示輸入變數,out表示輸出變數,inout輸入輸出均可 create procedure myprocedure([IN|OUT|INOUT] 引數名 資料型別, [IN|OUT|INOUT] 引數名 資料型別, ...) begin ... end ``` 儲存函式: ```mysql create function myfunction(引數名 資料型別, ...) returns 返回型別 begin ... end ``` 二者區別: - 儲存函式限制較多,例如不能使用臨時表,只能用表變數,而儲存過程限制較少; - 儲存過程可以實現複雜的功能,儲存函式針對性比較強; - 返回值不同,儲存過程可以沒有返回值,也可以返回單個或多個結果集,而儲存函式有且僅有一個返回值; - 呼叫不同。儲存過程通過call語句呼叫,儲存函式通過select呼叫; - 引數不同。儲存過程的引數型別可以是in、out、inout,而儲存函式的引數型別只有in型別。 ### 16、觸發器 SQL觸發器是一種特殊型別的儲存過程,不由使用者呼叫。它在指定的表中的資料發生變化時自動生效。喚醒呼叫觸發器以響應Insert、Update和Delete語句。他可以查詢其它表,並可以包含複雜的Transact-SQL語句。將觸發器和觸發它的語句作為可在觸發器內回滾的單個事務對待。如果檢測到嚴重錯誤,整個事務自動回滾。 優點: - 觸發器可通過資料庫中的相關表實現級聯更改; - 觸發器可以強制比用check約束定義的約束更為複雜的約束; - 在約束所支援的功能無法滿足應用程式的功能要求時,觸發器就極為有用。 ```mysql create trigger trigger_order after insert on orders for each row begin update product set pnum = pnum - new.onum where pid = new.pid; end ``` ### 17、資料庫的鎖機制 MyISAM和InnoDB儲存引擎使用的鎖: MyISAM採用表級鎖(table-level locking),InnoDB支援行級鎖(row-level locking)和表級鎖,預設為行級鎖。 二者對比: - 表級鎖:MySQL中粒度最大的鎖,對當前操作的整張表加鎖,實現簡單,資源消耗少,加鎖快,不會出現死鎖。鎖衝突的概率高,併發度低。 - 行級鎖:MySQL中粒度最小的鎖,只針對當前操作的行進行加鎖。行級鎖能大大減少資料庫操作的衝突。加鎖慢,開銷大,併發度高,會出現死鎖。 InnoDB引擎的鎖演算法: - Record lock:記錄鎖。條件為精準匹配時,鎖住具體的索引項; - Gap lock:間隙鎖。鎖定一個範圍,不包括記錄本身。 - Next-key lock:臨鍵鎖。鎖定一個範圍,包含記錄本身。 按思想分為樂觀鎖和悲觀鎖 - 樂觀鎖:事務併發操作時認為不會發生衝突,對資料進行更新並提交,如果檢測到衝突就返回。 - 悲觀鎖:事務併發操作使認為會發生衝突,先進行加鎖操作。 ### 18、日誌 **bin log**:二進位制日誌(服務層):涉及到主從複製; **redo log**:重做日誌(引擎層):資料的災後重新提交,物理日誌。包括兩部分,記憶體中的日誌快取(redo log buffer)(易失性)和磁碟上的重做日誌(redo log file)(永續性),需要將redo log buffer通過作業系統核心空間的OS buffer刷到磁碟上的log file中。 **undo log**:回滾日誌(引擎層):主要用於資料修改的回滾,邏輯日誌。會給予與操作相反的語句,當事務回滾時從undo log中反向讀取內容。 **MVCC**:Multiversion concurrency control,多版本併發控制,實現併發和回滾的重要功能。它指的是資料庫中的每一條資料,會存在多個版本。對同一條資料而言,MySQL 會通過一定的手段(ReadView 機制)控制每一個事務看到不同版本的資料,這樣也就解決了不可重複讀的問題。 ### 19、解決幻讀 在`Innodb`引擎中,每條聚集索引都會有兩個隱藏欄位:`trx_id`和`roll_pointer`,每次事務對一條記錄進行改動時,就會將`事務id`賦值給`trx_id`,並且會將舊資料寫入一條undo日誌,每條undo日誌都有`roll_pointer`屬性,可以將這些undo日誌都連起來,串成一個連結串列,undo日誌的寫入採用頭插法,新資料在前。 - **快照讀:** `MVCC`中有一個`ReadView`的概念,其中記錄了生成`ReadView`時的`活躍事務id列表:m_ids`、`最小事務id:min_trx_id`、`將要分配給下一個事務的id:max_trx_id`、`生成ReadView的事務id:creator_trx_id`。如果被訪問版本的`trx_id`與`creator_trx_id`相同或者小於`min_trx_id`,則可以訪問;如果被訪問版本的`trx_id`大於等於`max_trx_id`,則不能訪問;如果被訪問版本的`trx_id`在`min_trx_id`和`max_trx_id`之間,則當`trx_id`不在`m_ids`中時才能訪問。 - **當前讀:** `InnoDB`儲存引擎有三種鎖:`Record lock`:單個行記錄上的鎖;`Gap lock`:間隙鎖,鎖定一個範圍,不包括記錄本身;`Next-key lock`:`record+gap` 鎖定一個範圍,包含記錄本身。`innodb`對於行的查詢使用`next-key lock`,當查詢的索引含有唯一屬性時,將`next-key lock`降級為`record key`。 ### 20、資料庫的索引機制 需要建立索引的情況: - 主鍵自動建立唯一索引; - 頻繁作為查詢條件的欄位; - 查詢與其它表關聯的欄位,外來鍵關係建立索引; - 查詢中排序的欄位(通過索引訪問將大大提高排序速度); - 查詢中統計或分組的欄位。 不需要建立索引的情況: - 表記錄太少; - 經常增刪改的表; - 頻繁更新的欄位; - where條件裡用不到的欄位; - 資料重複且分佈平均的欄位 ### 21、explain關鍵字 id:選擇識別符號;select_type:查詢的型別;table:輸出結果集的表;type:表的連線型別;possible_keys:可能使用的索引;key:實際使用的索引;key_len:索引欄位的長度;ref:列與索引的比較;rows:掃描出的行數;extra:執行情況的描述和說明。 ### 22、索引優化思路 開啟慢查詢日誌設定閾值;explain做慢SQL分析。 查詢擷取分析:using filesort效率低,using index效率高;最左字首原則 ### 23、索引建立規則 最左字首匹配原則:mysql會一直向右匹配指導遇到範圍查詢(betwee、like)就停止查詢;選擇區分度高的列作為索引;選擇唯一性索引;儘量使用資料量少的索引;儘量使用字首來索引;索引列不能參與計算;儘量的擴充套件索引不要新建索引;限制索引的數目。 ### 24、索引過多的問題 一般一個表對應5個索引左右,索引過多會導致:查詢資料變慢;對insert語句影響很大,尤其是無序插入;刪除資料多的情況下索引也需要更新;索引檔案過大,佔用儲存空間,定址的查詢時間長;mysql優化器需要評估更多的