数据库学习笔记2
0413
數(shù)據(jù)庫學(xué)習(xí)筆記2
- 第一、二、三、四、五章
- 六、事務(wù)(TRANSACTION)
- 28.事務(wù)ACID原則、臟讀、不可重復(fù)讀、幻讀
- 29. 測試事務(wù)實現(xiàn)轉(zhuǎn)賬
- 執(zhí)行事務(wù):(原理)
- 示例:(**轉(zhuǎn)賬實現(xiàn)**)
- 注意:(在實際應(yīng)用中)
- 七、索引(index)
- 30,31小結(jié)
- 30.索引的 介紹、分類、添加、示例
- 31. SQL編程創(chuàng)建100萬條數(shù)據(jù)測試索引
- 32. 索引的 原則、數(shù)據(jù)結(jié)構(gòu)
- 索引的原則:
- 索引的數(shù)據(jù)結(jié)構(gòu):
- 32' 補充1: BTree索引(32中參考鏈接的內(nèi)容)
- 32'' 補充2:數(shù)據(jù)結(jié)構(gòu)教材的 第八章 查找算法
- 8.2 基于 線性表 的查找法
- 8.3 基于 樹 的查找法
- 補充:紅黑樹和AVL樹的詳解和區(qū)別
- 8.4 計算式查找法(哈希表)
- 八、權(quán)限管理和備份
- 33. 數(shù)據(jù)庫用戶管理
- 34. MySQL備份
- 在sqlyog這種可視化工具中手動導(dǎo)出
- 使用命令行`mysqldump`導(dǎo)出
- 九、規(guī)范數(shù)據(jù)庫設(shè)計
- 35. 如何設(shè)計一個項目的數(shù)據(jù)庫
- 36.數(shù)據(jù)庫的三大范式(了解)
- 十、JDBC(重點)
- 37. 數(shù)據(jù)庫驅(qū)動 和 JDBC
- 38-44
- 45. 數(shù)據(jù)庫連接池
第一、二、三、四、五章
點這里
六、事務(wù)(TRANSACTION)
28.事務(wù)ACID原則、臟讀、不可重復(fù)讀、幻讀
1.什么是事務(wù)?
事務(wù)就是將一組SQL語句放在同一批次內(nèi)去執(zhí)行;
如果一個SQL語句出錯,則該批次內(nèi)的所有SQL都將被取消執(zhí)行;(要么都成功,要么都失敗)
MySQL事務(wù)處理只支持InnoDB和BDB數(shù)據(jù)表類型。
2.事務(wù)原則(巨重要)
ACID原則:原子性(Atomicity) 、一致性(Consistency)、隔離性(Isolation)、持久性(Durability) (臟讀,幻讀,不可重復(fù)讀…)
參考博客鏈接:事務(wù)ACID理解
原子性(Atomicity):
- 原子性是指事務(wù)是一個不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。或者說是兩個操作要么一起成功,或者一起失敗,不能只發(fā)生其中一個動作。
一致性(Consistency):
- 事務(wù)前后數(shù)據(jù)的完整性必須保持一致。針對一個事務(wù)操作前與操作后的狀態(tài)一致。例如:兩個人轉(zhuǎn)賬,兩人一共1000塊,操作前和操作后的總和都是1000。
隔離性(Isolation):
- 事務(wù)的隔離性是多個用戶并發(fā)訪問數(shù)據(jù)庫時,數(shù)據(jù)庫為每一個用戶開啟的事務(wù),不能被其他事務(wù)的操作數(shù)據(jù)所干擾,多個并發(fā)事務(wù)之間要相互隔離。
持久性(Durability):
- 持久性是指一個事務(wù)一旦被提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對其有任何影響,即事務(wù)結(jié)束后的數(shù)據(jù)不會因為外界原因?qū)е聰?shù)據(jù)丟失;
- 舉例:
操作前A:800,B:200
操作后A:600,B:400
如果在操作前(事務(wù)還沒有提交)服務(wù)器宕機或者斷電,那么重啟數(shù)據(jù)庫以后,數(shù)據(jù)狀態(tài)應(yīng)該為
A:800,B:200 – 相當(dāng)于沒發(fā)生,回滾到事務(wù)開始前的狀態(tài)
如果在操作后(事務(wù)已經(jīng)提交)服務(wù)器宕機或者斷電,那么重啟數(shù)據(jù)庫以后,數(shù)據(jù)狀態(tài)應(yīng)該為
A:600,B:400 – 即實務(wù)操作成功后,帶來的改變是不可逆的。
隔離所導(dǎo)致的一些問題:
①臟讀(Dirty Read):
- 指一個事務(wù)讀取了另外一個事務(wù)未提交的數(shù)據(jù)的現(xiàn)象就是臟讀。
- 例如:
在事務(wù)A執(zhí)行過程中,事務(wù)A對數(shù)據(jù)資源進行了修改,事務(wù)B讀取了事務(wù)A修改后的數(shù)據(jù);
由于某些原因,事務(wù)A并沒有完成提交,發(fā)生了RollBack操作,則事務(wù)B讀取的數(shù)據(jù)就是臟數(shù)據(jù)。
②不可重復(fù)讀(Nonrepeatable Read):
- 在同一個事務(wù)中讀取表中的某一行數(shù)據(jù),前后兩次讀取的數(shù)據(jù)不一致的現(xiàn)象就是不可重復(fù)讀(Nonrepeatable Read)。(這個不一定是錯誤,只是某些場合不對)
- 例如:
事務(wù)B讀取了兩次數(shù)據(jù)資源,在這兩次讀取的過程中事務(wù)A修改了數(shù)據(jù),導(dǎo)致事務(wù)B在這兩次讀取出來的數(shù)據(jù)不一致。 - 不可重復(fù)讀強調(diào)的是單條數(shù)據(jù)的更新。
③虛讀(幻讀):
- 是指在一個事務(wù)內(nèi)讀取到了別的事務(wù)插入的數(shù)據(jù),導(dǎo)致前后讀取數(shù)量總量不一致。(一般是行影響,如下圖所示:多了一行)
- 例如:
事務(wù)B前后兩次讀取同一個范圍的數(shù)據(jù),在事務(wù)B兩次讀取的過程中事務(wù)A新增了數(shù)據(jù),導(dǎo)致事務(wù)B后一次讀取到前一次查詢沒有看到的行。 - 幻讀強調(diào)的是整個集合的增減。
注意:
幻讀和不可重復(fù)讀有些類似,但是幻讀強調(diào)的是集合的增減,而不可重復(fù)讀強調(diào)的是單條數(shù)據(jù)的更新。
29. 測試事務(wù)實現(xiàn)轉(zhuǎn)賬
執(zhí)行事務(wù):(原理)
mysql 是默認開啟事務(wù)自動提交,即autocommit = 1
所以要手動處理事務(wù),就要①先關(guān)閉(系統(tǒng)默認的)事務(wù)自動提交的設(shè)置:
②然后就可以手動處理事務(wù)了,先開啟事務(wù):
-- 事務(wù)開啟 START TRANSACTION; -- 標記一個事務(wù)的開始,從這個之后的sql都在同一個事務(wù)內(nèi)③然后是一組sql:
INSERT XX INSERT XX④執(zhí)行完這一組sql,可以有以下兩種操作:
-- 回滾 : 只要沒COMMIT,就還可以滾回到的原來的樣子 ROLLBACK; -- 提交 : 持久化(一旦提交,再回滾也滾不回去了) COMMIT;⑤最后結(jié)束手動處理事務(wù),即恢復(fù)到系統(tǒng)默認設(shè)置autocommit = 1
-- 事務(wù)結(jié)束 SET autocommit = 1; -- 開啟自動提交(系統(tǒng)默認設(shè)置)綜上:
-- 手動處理事務(wù) -- 1. SET autocommit = 0; -- 關(guān)閉自動提交 -- 2. -- 事務(wù)開啟 START TRANSACTION; -- 標記一個事務(wù)的開始,從這個之后的sql都在同一個事務(wù)內(nèi) -- 3. INSERT XX INSERT XX -- 4. -- 回滾 : 只要沒COMMIT,就還可以滾回到的原來的樣子 ROLLBACK; -- 提交 : 持久化(一旦提交,再回滾也滾不回去了) COMMIT; --5. -- 事務(wù)結(jié)束 SET autocommit = 1; -- 開啟自動提交-- 補充:(了解) SAVEPOINT 保存點名 -- 設(shè)置一個事務(wù)的保存點 ROLLBACK TO SAVEPOINT 保存點名 -- 回滾到保存點 RELEASE SAVEPOINT 保存點名 -- 撤銷保存點示例:(轉(zhuǎn)賬實現(xiàn))
-- 創(chuàng)建數(shù)據(jù)庫: CREATE DATABASE `shop` CHARACTER SET utf8 COLLATE utf8_general_ci; -- 創(chuàng)建數(shù)據(jù)表: CREATE TABLE `account` (`id` INT(4) NOT NULL AUTO_INCREMENT,`name` VARCHAR(20) NOT NULL,`money` DECIMAL(10,2) NOT NULL, -- VARCHAR(30)PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 -- 插入數(shù)據(jù) INSERT INTO `account` VALUES(12,'小王',1000),(16,'小張',800)-- 執(zhí)行事務(wù): -- 1.關(guān)閉自動提交 SET autocommit = 0 -- 2.開啟事務(wù) START TRANSACTION -- 3.一組sql(雖然是一組sql,但也要挨個單句執(zhí)行,多句執(zhí)行應(yīng)該可以,但現(xiàn)在是初學(xué)階段) UPDATE `account` SET `money` = `money` - 20 WHERE `name`='小王' UPDATE `account` SET `money` = `money` + 20 WHERE `name`='小張' -- 4.只要沒COMMIT,就可以回滾;一旦提交,再回滾也滾不回去了 ROLLBACK COMMIT -- 5.恢復(fù)系統(tǒng)的默認設(shè)置 SET autocommit = 1結(jié)果:
執(zhí)行事務(wù)之前:
執(zhí)行事務(wù)之后:
(只要沒執(zhí)行COMMIT,通過執(zhí)行ROLLBACK是可以回到上上張圖片的;一旦執(zhí)行COMMIT,信息就永久更新,不可逆)
注意:(在實際應(yīng)用中)
上面的示例只是手動去處理事務(wù),在實際應(yīng)用中,會把上面示例中的第3步和第4步放在一個try...catch...中,如果要執(zhí)行的一組sql沒有問題,能成功運行,就自動COMMIT,如果運行失敗,相當(dāng)于是異常情況,就跳到catch中自動回滾。
七、索引(index)
30,31小結(jié)
30主要講了以下內(nèi)容:
- 啥是索引:是一種數(shù)據(jù)結(jié)構(gòu),用它可以快速找到數(shù)據(jù)。
- 索引的分類:主鍵索引(只能有一個)、唯一索引、常規(guī)索引、全文索引。
- 添加索引的三種方式:1.創(chuàng)建數(shù)據(jù)表的時候;2.用ALTER創(chuàng)建;3.用CREATE創(chuàng)建。
- 刪除索引:DROP INDEX 索引名 ON 表名字;
- 查看所有索引:SHOW INDEX FROM 表名;
- 然后用全文索引寫了個例子,來說明有索引和沒索引的區(qū)別:沒索引就是整個數(shù)據(jù)表去搜索,有索引就是直接一下子找到。
這里面用了關(guān)鍵字EXPLAIN來查看sql執(zhí)行的狀況,相當(dāng)于是個工具,可以查看這次查詢一共用了多久的時間,查找了多少行數(shù)據(jù)。
31中又寫了一個例子,依然是全文索引:
- 把數(shù)據(jù)量增加到100萬條;
- 用了一個函數(shù)mock_data(),先把這個函數(shù)寫好;
- 然后執(zhí)行這個函數(shù)SELECT mock_data();
- 然后又借助關(guān)鍵字EXPLAIN來說明加索引和不加索引的區(qū)別:不加索引,查一條數(shù)據(jù)要用1s多,加上索引再查這條數(shù)據(jù)只用0.01s。
結(jié)論:索引在小數(shù)據(jù)量的時候,用處不大,但是在大數(shù)據(jù)的時候,優(yōu)勢十分明顯。
30.索引的 介紹、分類、添加、示例
索引的定義:
- 索引(index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
索引的本質(zhì):
- 索引是數(shù)據(jù)結(jié)構(gòu)。
索引的作用:
- 提高查詢速度;
- 確保數(shù)據(jù)的唯一性;
- 可以加速表和表之間的連接 , 實現(xiàn)表與表之間的參照完整性;
- 使用分組和排序子句進行數(shù)據(jù)檢索時 , 可以顯著減少分組和排序的時間;
- 全文檢索字段進行搜索優(yōu)化。
索引的分類:
- 主鍵索引(primary key):
唯一的標識,主鍵的內(nèi)容不可重復(fù),且只能有一個列(字段)作為主鍵。 - 唯一索引(unique key):
避免出現(xiàn)重復(fù)的列名(字段名),可以有多個唯一索引,即可以將多個列標識為唯一索引。 - 常規(guī)索引(key / index):
默認的index 或者 key 關(guān)鍵字 - 全文索引(FullText index):
在特定的數(shù)據(jù)庫引擎下才有,如MYISAM;
可以快速定位數(shù)據(jù)。
注意:主鍵索引只能有一個;唯一索引可以有多個。
添加所有的三種方式:
參考鏈接:數(shù)據(jù)庫創(chuàng)建索引和刪除索引的方式總結(jié)
1.創(chuàng)建表時給字段增加索引
注意:因為主鍵索引是唯一的,所以不需要索引名,直接在括號里寫字段名即可。
2.用ALTER在已建好的表上創(chuàng)建索引
3.用CREATE在已建好的表上創(chuàng)建索引
語法:create index 索引名 on 表名(字段)
注意:Create不能用于創(chuàng)建Primary key索引
其他操作:(刪除索引、顯示索引信息)
-- 刪除索引: DROP INDEX 索引名 ON 表名字; DROP INDEX `name` ON `student` -- 示例 -- 刪除主鍵索引: ALTER TABLE 表名 DROP PRIMARY KEY; ALTER TABLE 表名 DROP INDEX 索引名;-- 顯示索引信息: SHOW INDEX FROM 表名;一個完整的示例:
-- 顯示所有的索引信息: SHOW INDEX FROM `student` -- 創(chuàng)建一個索引: CREATE INDEX `name` ON `student` (`studentname`) -- 刪除索引: DROP INDEX `name` ON `student`-- 用explain來查看sql執(zhí)行的狀況,相當(dāng)于是個工具,可以查看這次查詢一共用了多久的時間,查找了多少行數(shù)據(jù) -- 非全文索引: SELECT * FROM `student` WHERE `studentname`='張偉強' EXPLAIN SELECT * FROM `student` WHERE `studentname`='張偉強'-- 增加全文索引: ALTER TABLE `student` ADD FULLTEXT INDEX `name`(`studentname`); -- 全文索引: SELECT * FROM `student` WHERE `studentname`='張偉強' EXPLAIN SELECT * FROM `student` WHERE MATCH(`studentname`) AGAINST('張偉強');示例所用到的數(shù)據(jù)表:
結(jié)果:
查看所有索引:
非全文索引:
添加全文索引:
全文索引:
解釋下上面的全文索引:
– 全文搜索通過 MATCH() 函數(shù)完成。
– 搜索字符串作為 against() 的參數(shù)被給定。搜索以忽略字母大小寫的方式執(zhí)行。對于表中的每個記錄行,MATCH() 返回一個相關(guān)性值。即,在搜索字符串與記錄行在 MATCH() 列表中指定的列的文本之間的相似性尺度。
補充:
全文索引的版本、存儲引擎、數(shù)據(jù)類型的支持情況:
- MySQL 5.6 以前的版本,只有 MyISAM 存儲引擎支持全文索引;
- MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存儲引擎均支持全文索引;
- 只有字段的數(shù)據(jù)類型為 char、varchar、text 及其系列才可以創(chuàng)建全文索引;
- 測試或使用全文索引時,要先看一下自己的 MySQL 版本、存儲引擎和數(shù)據(jù)類型是否支持全文索引。
參考鏈接:
【MySQL優(yōu)化】——看懂explain_漫漫長途,終有回轉(zhuǎn);余味苦澀,終有回甘-CSDN博客_explain
31. SQL編程創(chuàng)建100萬條數(shù)據(jù)測試索引
1.建表app_user:
CREATE TABLE app_user (`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',`name` VARCHAR(50) DEFAULT '' COMMENT '用戶昵稱',`email` VARCHAR(50) NOT NULL COMMENT '用戶郵箱',`phone` VARCHAR(20) DEFAULT '' COMMENT '手機號',`gender` TINYINT(4) UNSIGNED DEFAULT '0' COMMENT '性別(0:男 1:女)',`password` VARCHAR(100) NOT NULL COMMENT '密碼',`age` TINYINT(4) DEFAULT '0' COMMENT '年齡',`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',`update_time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='app用戶表'2.批量插入100w條數(shù)據(jù):(mock_data()是個函數(shù))
DELIMITER $$ -- 寫函數(shù)之前必須要寫,標志 CREATE FUNCTION mock_data() RETURNS INT BEGINDECLARE num INT DEFAULT 1000000;DECLARE i INT DEFAULT 0;WHILE i<num DOINSERT INTO app_user(`name`,`email`,`phone`,`gender`,`password`,`age`)VALUES(CONCAT('用戶',i),'123345@qq.com',CONCAT('18',FLOOR(RAND()*((999999999-100000000)+100000000))),FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100));SET i = i+1;END WHILE;RETURN i; END;-- 執(zhí)行函數(shù) SELECT mock_data();-- 查表 SELECT * FROM app_user;3.測試:
-- 測試: -- 查看索引信息: SHOW INDEX FROM `app_user`-- 刪除索引: DROP INDEX id_app_user_name ON `app_user`SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 1.260 sec EXPLAIN SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 0.002 sec-- 創(chuàng)建索引: -- id_表名_字段名 索引名 -- CREATE INDEX 索引名 ON 表名(`字段名`); CREATE INDEX id_app_user_name ON app_user(`name`);SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 0.001 sec EXPLAIN SELECT * FROM app_user WHERE `name` = '用戶9999'; -- 0.001 sec結(jié)果:
不加索引:
加索引:
查看索引信息:
結(jié)論:
索引在小數(shù)據(jù)量的時候,用處不大,但是在大數(shù)據(jù)的時候,區(qū)分十分明顯。
32. 索引的 原則、數(shù)據(jù)結(jié)構(gòu)
索引的原則:
- 索引不是越多越好;
- 不要對經(jīng)常變動的數(shù)據(jù)加索引;
- 小數(shù)據(jù)量的表建議不要加索引;
- 索引一般應(yīng)加在查找條件的字段。
索引的數(shù)據(jù)結(jié)構(gòu):
1.Hash類型的索引;
2.BTree(B樹):INNODB引擎默認的數(shù)據(jù)結(jié)構(gòu);
3.全文索引。
– 我們可以在創(chuàng)建上述索引的時候,為其指定索引類型,分兩類
hash類型的索引:查詢單條快,范圍查詢慢
btree類型的索引:b+樹,層數(shù)越多,數(shù)據(jù)量指數(shù)級增長(我們就用它,因為innodb默認支持它)
– 不同的存儲引擎支持的索引類型也不一樣
InnoDB 支持事務(wù),支持行級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
MyISAM 不支持事務(wù),支持表級別鎖定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
Memory 不支持事務(wù),支持表級別鎖定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
NDB 支持事務(wù),支持行級別鎖定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;
Archive 不支持事務(wù),支持表級別鎖定,不支持 B-tree、Hash、Full-text 等索引;
參考鏈接:MySQL索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理
32’ 補充1: BTree索引(32中參考鏈接的內(nèi)容)
摘要:
MySQL數(shù)據(jù)庫支持多種索引類型,如BTree索引,哈希索引,全文索引等等。
為了避免混亂,本文將只關(guān)注于BTree索引,因為這是平常使用MySQL時主要打交道的索引,至于哈希索引和全文索引本文暫不討論。
第一部分:數(shù)據(jù)機構(gòu)及算法基礎(chǔ)
數(shù)據(jù)庫查詢是數(shù)據(jù)庫的最主要功能之一,我們都希望查詢數(shù)據(jù)的速度能盡可能的快。
常見的查詢算法有
- 順序查找(linear search):這種復(fù)雜度為O(n)的算法在數(shù)據(jù)量很大時顯然是糟糕的。
- 二分查找(binary search):二分查找要求被檢索數(shù)據(jù)有序;
- 二叉樹查找(binary tree search):二叉樹查找只能應(yīng)用于二叉查找樹上;
二叉查找樹的改進:平衡二叉樹(AVL樹)+ 紅黑樹 -->見下面的 8.3 基于 樹 的查找法 補充:紅黑樹和AVL樹的詳解和區(qū)別
在實際的數(shù)據(jù)庫系統(tǒng)幾乎沒有使用二叉查找樹或其進化品種紅黑樹(red-black tree)實現(xiàn),因為數(shù)據(jù)本身的組織結(jié)構(gòu)不可能完全滿足各種數(shù)據(jù)結(jié)構(gòu)(例如,理論上不可能同時將兩列都按順序進行組織)。所以在數(shù)據(jù)之外,數(shù)據(jù)庫系統(tǒng)還維護著滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)上實現(xiàn)高級查找算法,這種數(shù)據(jù)結(jié)構(gòu)就是索引(index)。
目前大部分數(shù)據(jù)庫系統(tǒng)及文件系統(tǒng)都采用B-Tree或其變種B+Tree作為索引結(jié)構(gòu)。
B樹:(1)–>(2)–>(3)
(1)二叉排序樹,又叫二叉查找樹:
- 若左子樹為空,則左子樹上所有結(jié)點的值均小于根結(jié)點的值;
若右子樹為空,則右子樹上所有結(jié)點的值均大于等于根結(jié)點的值;
左右子樹也分別為二叉排序樹。 - 中序遍歷一個二叉排序樹可以得到一個遞增有序序列。
(2)m叉排序樹,又叫m路查找樹:
- 一個結(jié)點最多有m棵子樹,m-1個關(guān)鍵字;
- 子樹Pi中的所有關(guān)鍵字均大于Ki,小于K(i+1);
- 子樹P0中的關(guān)鍵字均小于K1,子樹Pn中的所有關(guān)鍵字均大于Kn;
- 子樹Pi也是m路查找樹
- 書本P289的例8.7
- (3)B樹,一顆平衡的m路查找樹:
- 每個結(jié)點做多有m棵子樹;
- 根結(jié)點至少有2棵子樹;
- 除根結(jié)點之外的所有非葉結(jié)點至少有ceiling(m/2)棵子樹,ceiling(m/2) - 1個關(guān)鍵字;
- 所有葉結(jié)點在同一層,也叫失敗結(jié)點;
- B樹是“從葉向根”生長的,而根對每個分支是公用的,所以不論根長到多“深”,各分支的長度同步增長,因而各分支是“平衡”的;
- 書中P289的例8.8、8.9,—B樹的基本性質(zhì)
P293的例8.10,8.11,—B樹中插入一個關(guān)鍵字
P296的例8.12,8.13,—B樹中刪除一個關(guān)鍵字
**B樹**有許多變種,其中最常見的是B+Tree,例如MySQL就普遍使用B+Tree實現(xiàn)其索引結(jié)構(gòu)。那么B樹和B+樹區(qū)別在哪?
參考鏈接1:簡單剖析B樹(B-Tree)與B+樹
常說的B-樹就是B樹,沒有所謂的B減樹。
聚集索引(Clustered Index)、非聚集索引(NonClustered Index)、衛(wèi)星數(shù)據(jù)?
B+樹相比B樹的優(yōu)勢:
1.單一節(jié)點存儲更多的元素,使得查詢的IO次數(shù)更少;
2.所有查詢都要查找到葉子節(jié)點,查詢性能穩(wěn)定;
3.所有葉子節(jié)點形成有序鏈表,便于范圍查詢。
參考鏈接2:B樹和B+樹
不同數(shù)據(jù)庫引擎(MYISAM引擎和INNODB引擎)中B+樹的差異:。
參考鏈接3:B樹與B+樹簡明扼要的區(qū)別
參考鏈接4:面試總結(jié):B樹,B+樹的原理及區(qū)別
參考鏈接5:面試題:B(B-)樹,B+樹,B樹和B+樹的區(qū)別,B樹和B+樹的優(yōu)點
參考鏈接6:B樹、B-樹、B+樹、B*樹之間的關(guān)系
第二部分:MySQL索引實現(xiàn):
- MyISAM索引實現(xiàn)
- InnoDB索引實現(xiàn)
第三部分:索引使用策略及優(yōu)化
32’’ 補充2:數(shù)據(jù)結(jié)構(gòu)教材的 第八章 查找算法
8.2 基于 線性表 的查找法
- 順序查找法:
- 折半查找法:順序存儲、數(shù)據(jù)有序
- 分塊查找法:創(chuàng)建一個索引表,每個索引項記錄一個塊的起始位置和塊中的最大關(guān)鍵字,索引表按關(guān)鍵字有序排列(即塊之間有序,塊內(nèi)無序)。先用順序查找或折半查找鎖定塊,然后在塊內(nèi)用順序查找法。
8.3 基于 樹 的查找法
- 二叉排序樹:(二叉查找樹)
若左子樹為空,則左子樹上所有結(jié)點的值均小于根結(jié)點的值;
若右子樹為空,則右子樹上所有結(jié)點的值均大于等于根結(jié)點的值;
左右子樹也分別為二叉排序樹。
中序遍歷一個二叉排序樹可以得到一個遞增有序序列。 - 平衡二叉排序樹:(AVL樹)
左右子樹的高度之差的絕對值小于等于1;左右子樹也是平衡二叉排序樹。
結(jié)點的平衡因子(Balance Factor)是指結(jié)點的左右子樹深度之差,AVL樹中所有結(jié)點的平衡因子只能是-1、0、1。
給一個AVL樹上插入一個結(jié)點,可能導(dǎo)致樹失衡,失衡類型及相應(yīng)的調(diào)整方法可歸納為四種:LL型、LR型、RR型、RL型。
紅黑樹和AVL樹的區(qū)別:(見下面的詳解) - B樹:
見教材的P288 - P298,或者直接看上面的32’ 補充1:BTree索引
補充:紅黑樹和AVL樹的詳解和區(qū)別
(參考鏈接:紅黑樹和AVL樹(平衡二叉樹)區(qū)別、鏈接2)
AVL樹是嚴格的平衡二叉樹,一旦失衡就要通過旋轉(zhuǎn)來保持平衡,而旋轉(zhuǎn)是非常耗時的,因此AVL樹適合用于插入與刪除次數(shù)比較少,但查找比較多的情況。由于維護這種高度平衡所付出的代價比從中獲得的效率收益還大,故而實際的應(yīng)用不多,更多的地方是用追求局部而不是非常嚴格整體平衡的紅黑樹。當(dāng)然,如果應(yīng)用場景中對插入、刪除不頻繁,只是對查找要求較高,那么AVL還是較優(yōu)于紅黑樹。
紅黑樹是一種二叉查找樹,但在每個節(jié)點增加一個存儲位表示節(jié)點的顏色,可以是紅或黑(非紅即黑)。通過對任何一條從根到葉子的路徑上各個節(jié)點著色的方式的限制,紅黑樹確保沒有一條路徑會比其它路徑長出兩倍,因此,紅黑樹是一種弱平衡二叉樹(由于是弱平衡,可以看到,在相同的節(jié)點情況下,AVL樹的高度低于紅黑樹),相對于要求嚴格的AVL樹來說,紅黑樹的旋轉(zhuǎn)次數(shù)少,插入,刪除,查找的復(fù)雜度都是O(log N),所以對于搜索,插入,刪除操作較多的情況下,就用紅黑樹。。
紅黑樹的規(guī)則:
- 規(guī)則1: 每個節(jié)點不是黑色就是紅色(非紅即黑);
- 規(guī)則2: 根節(jié)點為黑色;
- 規(guī)則3:紅色節(jié)點的父節(jié)點和子節(jié)點不能為紅色;紅色結(jié)點的兩兒子都是黑的
- 規(guī)則4:所有的葉子節(jié)點都是黑色(空節(jié)點視為葉子節(jié)點NIL);
- 規(guī)則5:任意一個節(jié)點到葉子節(jié)點的每條路徑上黑色節(jié)點的個數(shù)都相等;
- 規(guī)則6(特點):從根節(jié)點到葉子節(jié)點的最長的路徑不多于最短的路徑的長度的兩倍。
紅黑樹插入節(jié)點時的思路:(參考鏈接:紅黑樹與平衡二叉樹區(qū)別?)
插入的節(jié)點總是設(shè)為紅節(jié)點,當(dāng)其復(fù)節(jié)點為紅節(jié)點時,這就有破壞了規(guī)則3,就需要調(diào)整。將插入節(jié)點作為考察節(jié)點,考察其叔父,如果也是紅節(jié)點,則將其父親和叔父改為黑節(jié)點,而將其祖父改為紅節(jié)點,然后以其祖父為考察節(jié)點。如果其叔父是黑節(jié)點則做一旋轉(zhuǎn)變換可以搞定,沒有圖不太好說明,你可以自己考慮一下,總之它的思想是把“多出來”的紅色往上一層推去,確保下面層紅黑性質(zhì),最后推到根以后,如果依然違反性質(zhì)1,則可以直接把根由紅改黑即可,就相當(dāng)于把這“多出來”的紅色推到樹以外的節(jié)點去了。
刪除節(jié)點時先要找到頂替的節(jié)點,如果刪去的節(jié)點是黑色則破壞了規(guī)則5,也需要調(diào)整。調(diào)整的思想也同前面類似,把這個黑色賦予頂替節(jié)點,則頂替節(jié)點相當(dāng)于有兩重黑色,然后將它的兩重黑色向上推,一直推到根,再從根推到外面去了。
平衡二叉樹和紅黑樹的區(qū)別:
| 概念 | 嚴格的平衡二叉樹,左右子樹高度差的絕對值≤1 | 弱平衡樹,見上面的:紅黑樹的規(guī)則 |
| 失衡類型及相應(yīng)的調(diào)整方法 | LL型、LR型、RR型、RL型 | 見上面的紅黑樹插入節(jié)點時的思路 |
| 插入、刪除 | 因為要通過旋轉(zhuǎn)來恢復(fù)平衡,代價高 | O(log N) |
| 查找 | O(log N) | O(log N) |
| 應(yīng)用 | 適合用于插入與刪除次數(shù)比較少,但查找比較多的情況 如果應(yīng)用場景中對插入、刪除不頻繁,只是對查找要求較高,那么AVL還是較優(yōu)于紅黑樹。 | 對于查找,插入,刪除操作較多的情況下,就用紅黑樹; 廣泛用于C++的STL中,map和set都是用紅黑樹實現(xiàn)的 |
| 左右自述的高度差絕對值 | 小于等于1 | 某些時刻可能會超過1,但紅黑樹確保沒有一條路徑會比其它路徑長出兩倍,只要符合紅黑樹的規(guī)則即可 |
| 失衡后的具體操作 | 只要不平衡就會進行旋轉(zhuǎn) | 改變顏色+旋轉(zhuǎn) |
| 是否是高度平衡 | 是,嚴格的平衡二叉樹 | 否,弱平衡的二叉樹,插入最多兩次旋轉(zhuǎn),刪除最多三次旋轉(zhuǎn) |
多余的內(nèi)容:(不用看)
平衡二叉樹和紅黑樹的區(qū)別: + 平衡二叉樹的左右子樹的高度差絕對值不超過1, 但是紅黑樹在某些時刻可能會超過1,**紅黑樹確保沒有一條路徑會比其它路徑長出兩倍**,只要符合紅黑樹的五個條件即可; + 二叉樹**只要不平衡就會進行旋轉(zhuǎn)**, 而紅黑樹不符合規(guī)則時,**有些情況只用改變顏色不用旋轉(zhuǎn),就能達到平衡**; + AVL樹適合用于**插入與刪除次數(shù)比較少,但查找比較多**的情況, 對于**搜索,插入,刪除操作較多的情況**下,就用**紅黑樹**; + AVL 樹是**高度平衡的**,頻繁的插入和刪除,會引起頻繁的reblance,導(dǎo)致效率下降, 紅黑樹不是高度平衡的,算是一種折中,插入最多兩次旋轉(zhuǎn),刪除最多三次旋轉(zhuǎn)。8.4 計算式查找法(哈希表)
八、權(quán)限管理和備份
33. 數(shù)據(jù)庫用戶管理
方式一:用SQLyog可視化管理用戶
- 添加用戶;
- 刪除用戶;
- 管理用戶權(quán)限(全局權(quán)限、對某個數(shù)據(jù)庫的權(quán)限、對某個數(shù)據(jù)表的權(quán)限)
方式二:用sql命令管理用戶
(首先找到用戶表,在mysql數(shù)據(jù)庫–>user數(shù)據(jù)表中)
用sql命令對用戶進行管理,實質(zhì)上就是對用戶表進行增刪改查。
創(chuàng)建用戶、修改密碼、重命名、用戶授權(quán)、查看權(quán)限、撤銷權(quán)限、刪除用戶
授予權(quán)限的結(jié)果:
授予權(quán)限之前:
授予權(quán)限之后:(GRANT ALL PRIVILEGES ON *.* TO lele2)
權(quán)限解釋:
-- 權(quán)限列表 ALL [PRIVILEGES] -- 設(shè)置除GRANT OPTION之外的所有簡單權(quán)限 ALTER -- 允許使用ALTER TABLE ALTER ROUTINE -- 更改或取消已存儲的子程序 CREATE -- 允許使用CREATE TABLE CREATE ROUTINE -- 創(chuàng)建已存儲的子程序 CREATE TEMPORARY TABLES -- 允許使用CREATE TEMPORARY TABLE CREATE USER -- 允許使用CREATE USER, DROP USER, RENAME USER和REVOKE ALL PRIVILEGES。 CREATE VIEW -- 允許使用CREATE VIEW DELETE -- 允許使用DELETE DROP -- 允許使用DROP TABLE EXECUTE -- 允許用戶運行已存儲的子程序 FILE -- 允許使用SELECT...INTO OUTFILE和LOAD DATA INFILE INDEX -- 允許使用CREATE INDEX和DROP INDEX INSERT -- 允許使用INSERT LOCK TABLES -- 允許對您擁有SELECT權(quán)限的表使用LOCK TABLES PROCESS -- 允許使用SHOW FULL PROCESSLIST REFERENCES -- 未被實施 RELOAD -- 允許使用FLUSH REPLICATION CLIENT -- 允許用戶詢問從屬服務(wù)器或主服務(wù)器的地址 REPLICATION SLAVE -- 用于復(fù)制型從屬服務(wù)器(從主服務(wù)器中讀取二進制日志事件) SELECT -- 允許使用SELECT SHOW DATABASES -- 顯示所有數(shù)據(jù)庫 SHOW VIEW -- 允許使用SHOW CREATE VIEW SHUTDOWN -- 允許使用mysqladmin shutdown SUPER -- 允許使用CHANGE MASTER, KILL, PURGE MASTER LOGS和SET GLOBAL語句,mysqladmin debug命令;允許您連接(一次),即使已達到max_connections。 UPDATE -- 允許使用UPDATE USAGE -- “無權(quán)限”的同義詞GRANT OPTION -- 允許授予權(quán)限/* 表維護 */-- 分析和存儲表的關(guān)鍵字分布 ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE 表名 ... -- 檢查一個或多個表是否有錯誤 CHECK TABLE tbl_name [, tbl_name] ... [option] ... option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED} -- 整理數(shù)據(jù)文件的碎片 OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...34. MySQL備份
為什么要備份?
- 保證重要的數(shù)據(jù)不丟失;
- 數(shù)據(jù)轉(zhuǎn)移。
MySQL數(shù)據(jù)庫備份方法(三種方法)
- 1.直接拷貝數(shù)據(jù)庫文件和相關(guān)配置文件; – data文件夾(數(shù)據(jù)庫筆記1中有提及)
- 2.在sqlyog這種可視化工具中手動導(dǎo)出;-- 可視化操作
- 3.使用命令行mysqldump導(dǎo)出 。 – 命令行
在sqlyog這種可視化工具中手動導(dǎo)出
在想要導(dǎo)出的表或者庫中,右鍵:
注意下圖中三處框起來的地方即可:
使用命令行mysqldump導(dǎo)出
導(dǎo)出:
-- 導(dǎo)出一張表 : -- 格式:mysqldump -h主機 -u用戶名 -p密碼 數(shù)據(jù)庫 表名 >物理磁盤位置/文件名 mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql-- 導(dǎo)出多張表 : -- 格式:mysqldump -h主機 -u用戶名 -p密碼 數(shù)據(jù)庫 表名1 表名2 >物理磁盤位置/文件名 mysqldump -hlocalhost -uroot -p123456 school student result >D:/b.sql-- 導(dǎo)出整個數(shù)據(jù)庫 : -- 格式:mysqldump -h主機 -u用戶名 -p密碼 數(shù)據(jù)庫 >物理磁盤位置/文件名 mysqldump -hlocalhost -uroot -p123456 school >D:/c.sql導(dǎo)入:
方式一:(推薦)
- 先登錄;
- 切換到指定的數(shù)據(jù)庫;
- 然后source 備份文件。
(測試的時候可以先把school庫中的student表備份下來a.sql,然后把student表刪掉,然后按照上面的三個步驟導(dǎo)入)
方式二:(不推薦)
也可以這樣:
mysql -u用戶名 -p密碼 庫名 < 備份文件(要導(dǎo)入的文件)
九、規(guī)范數(shù)據(jù)庫設(shè)計
35. 如何設(shè)計一個項目的數(shù)據(jù)庫
為什么需要設(shè)計?
當(dāng)數(shù)據(jù)庫比較復(fù)雜的時候,我們就需要設(shè)計了。
糟糕的數(shù)據(jù)庫設(shè)計:
- 數(shù)據(jù)冗余,浪費空間;
- 數(shù)據(jù)庫插入和刪除都會麻煩、異常(屏蔽使用物理外鍵);
- 程序的性能差。
良好的數(shù)據(jù)庫設(shè)計:
- 節(jié)省內(nèi)存空間;
- 保證數(shù)據(jù)庫的完整性;
- 方便我們開發(fā)系統(tǒng)。
軟件項目開發(fā)周期中數(shù)據(jù)庫設(shè)計:
- 需求分析階段: 分析客戶的業(yè)務(wù)和數(shù)據(jù)處理需求
- 概要設(shè)計階段:設(shè)計數(shù)據(jù)庫的E-R模型圖 , 確認需求信息的正確和完整.
設(shè)計數(shù)據(jù)庫步驟:(個人博客)
第1步:收集信息
(與該系統(tǒng)有關(guān)人員進行交流 , 座談 , 充分了解用戶需求 , 理解數(shù)據(jù)庫需要完成的任務(wù))
- 用戶表(用戶登錄注銷,用戶的個人信息,寫博客,創(chuàng)建分類)
- 分類表(文章分類,誰創(chuàng)建的)
- 文章表(文章信息)
- 評論表
- 友鏈表(友情鏈接信息)
- 自定義表(系統(tǒng)信息,某個關(guān)鍵的字,或者一些主字段) key:value
- 關(guān)注表(粉絲數(shù))
- 說說表(發(fā)表心情,字段: id…content…create_time)
第2步:標識實體[Entity]
(把需求落地到每個字段,數(shù)據(jù)庫要管理的關(guān)鍵對象或?qū)嶓w,實體一般是名詞,標識每個實體需要存儲的詳細信息[Attribute])
- 用戶表:
- 分類表:
- 文章表:
- 評論表:
- 友鏈表:
- 關(guān)注表:
第3步:標識實體之間的關(guān)系[Relationship]
- 寫博客:user --> blog
- 創(chuàng)建分類:user --> category
- 關(guān)注:user --> user
- 友鏈:links
- 評論:user --> user --> blog
博客,bbs,Ant Design
36.數(shù)據(jù)庫的三大范式(了解)
問題 : 為什么需要數(shù)據(jù)規(guī)范化?
不合規(guī)范的表設(shè)計會導(dǎo)致的問題:
- 信息重復(fù);
- 更新異常;
- 插入異常:無法正確表示信息;
- 刪除異常:丟失有效信息。
三大范式:
第一范式 (1st NF):
- 原子性:保證每一列不可再分;
第二范式(2nd NF):
- 前提:滿足第一范式
- 每張表只描述一件事情;
第三范式(3rd NF):
- 前提:滿足第一范式和第二范式
- 第三范式需要確保數(shù)據(jù)表中的每一列數(shù)據(jù)都和主鍵直接相關(guān),而不能間接相關(guān)。
三大范式是用來規(guī)范數(shù)據(jù)庫的設(shè)計,但存在規(guī)范性和性能的問題(不可兼得的關(guān)系):
(阿里有句話:關(guān)聯(lián)查詢的表不得超過三張表)
- 考慮商業(yè)化的需求和目標(成本,用戶體驗)時,數(shù)據(jù)庫的性能更加重要;
- 在規(guī)范性能的問題的時候,需要綜合考慮一下規(guī)范性;
- 有時會故意給某些表增加一些冗余的字段(從多表查詢中變?yōu)閱伪聿樵?#xff09;,以大量減少需要從中搜索信息所需的時間;
- 有時會故意增加一些計算列(從大數(shù)據(jù)庫降低為小數(shù)據(jù)量的查詢:索引)。
十、JDBC(重點)
37. 數(shù)據(jù)庫驅(qū)動 和 JDBC
1.數(shù)據(jù)庫驅(qū)動
驅(qū)動:聲卡、顯卡、數(shù)據(jù)庫
應(yīng)用程序 通過 數(shù)據(jù)庫驅(qū)動 和 數(shù)據(jù)庫 打交道。
2.JDBC
UN公司為了簡化開發(fā)人員的(對數(shù)據(jù)庫的統(tǒng)一)操作,提供了一個(java操作數(shù)據(jù)庫的)規(guī)范,俗稱JDBC。
這些規(guī)范的實現(xiàn)由具體的廠商去做~
對于開發(fā)人員來說,我們只需要掌握JDBC接口的操作即可!
38-44
45. 數(shù)據(jù)庫連接池
數(shù)據(jù)庫連接 – 執(zhí)行完畢 – 釋放 整個過程中 連接-- 釋放 是十分浪費系統(tǒng)資源的,所以就有了
池化技術(shù):準備一些預(yù)先的資源,過來就連接預(yù)先準備好的。
最小連接數(shù):10(常用連接數(shù))
最大連接數(shù):100 (業(yè)務(wù)最高承載上線)
等待超時:100ms(等待超過100ms就會告訴客戶這里發(fā)生異常,讓客戶找別家)
編寫連接池,實現(xiàn)一個接口DataSource。
總結(jié):無論用什么數(shù)據(jù)源,本質(zhì)還是一樣的,DataSource接口不會變,方法就不會變。
(數(shù)據(jù)庫的課先學(xué)到這,2022-04-15 21:44:26)
總結(jié)
- 上一篇: 简单易学汇编语言入门_个人笔记
- 下一篇: Mysql utf8mb3 utf8mb