数据库学习笔记2

本文深入探讨了数据库中的事务处理,包括ACID原则、事务的隔离级别以及实例演示转账操作。接着讲解了索引的重要性和不同类型的索引,如BTree索引,以及如何通过索引来优化查询性能。此外,还介绍了数据库权限管理和备份的基本方法。最后,简要提及了JDBC和数据库连接池的概念。

0413

第一、二、三、四、五章

点这里

六、事务(TRANSACTION)

28.事务ACID原则、脏读、不可重复读、幻读

1.什么是事务?
事务就是将一组SQL语句放在同一批次内去执行
如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行;(要么都成功,要么都失败)
MySQL事务处理只支持InnoDB和BDB数据表类型。

2.事务原则(巨重要)
ACID原则:原子性(Atomicity) 、一致性(Consistency)、隔离性(Isolation)、持久性(Durability) (脏读,幻读,不可重复读…)

参考博客链接:事务ACID理解

原子性(Atomicity):

  • 原子性是指事务是一个不可分割的工作单位事务中的操作要么都发生,要么都不发生。或者说是两个操作要么一起成功,或者一起失败,不能只发生其中一个动作。

一致性(Consistency):

  • 事务前后数据的完整性必须保持一致。针对一个事务操作前与操作后的状态一致。例如:两个人转账,两人一共1000块,操作前和操作后的总和都是1000。

隔离性(Isolation):

  • 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

持久性(Durability):

  • 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响,即事务结束后的数据不会因为外界原因导致数据丢失;
  • 举例:
    操作前A:800,B:200
    操作后A:600,B:400
    如果在操作前(事务还没有提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
    A:800,B:200 – 相当于没发生,回滚到事务开始前的状态
    如果在操作后(事务已经提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为
    A:600,B:400 – 即实务操作成功后,带来的改变是不可逆的。

隔离所导致的一些问题:
脏读(Dirty Read)

  • 一个事务读取了另外一个事务未提交的数据的现象就是脏读
  • 例如:
    在事务A执行过程中,事务A对数据资源进行了修改,事务B读取了事务A修改后的数据
    由于某些原因,事务A并没有完成提交,发生了RollBack操作,则事务B读取的数据就是脏数据

不可重复读(Nonrepeatable Read)

  • 在同一个事务中读取表中的某一行数据,前后两次读取的数据不一致的现象就是不可重复读(Nonrepeatable Read)。(这个不一定是错误,只是某些场合不对)
  • 例如:
    事务B读取了两次数据资源,在这两次读取的过程中事务A修改了数据,导致事务B在这两次读取出来的数据不一致。
  • 不可重复读强调的是单条数据的更新在这里插入图片描述

③虚读(幻读):

  • 是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致。(一般是行影响,如下图所示:多了一行)
  • 例如:
    事务B前后两次读取同一个范围的数据,在事务B两次读取的过程中事务A新增了数据,导致事务B后一次读取到前一次查询没有看到的行。
  • 幻读强调的是整个集合的增减

在这里插入图片描述

注意:
幻读和不可重复读有些类似,但是幻读强调的是集合的增减,而不可重复读强调的是单条数据的更新

29. 测试事务实现转账

执行事务:(原理)

mysql 是默认开启事务自动提交,即autocommit = 1
所以要手动处理事务,就要①先关闭(系统默认的)事务自动提交的设置:

-- 关闭
SET autocommit = 0; 

②然后就可以手动处理事务了,先开启事务:

-- 事务开启
START TRANSACTION;  -- 标记一个事务的开始,从这个之后的sql都在同一个事务内

③然后是一组sql:

INSERT XX
INSERT XX

④执行完这一组sql,可以有以下两种操作:

-- 回滚 : 只要没COMMIT,就还可以滚回到的原来的样子 
ROLLBACK;
-- 提交 : 持久化(一旦提交,再回滚也滚不回去了)
COMMIT;

⑤最后结束手动处理事务,即恢复到系统默认设置autocommit = 1

-- 事务结束
SET autocommit = 1; -- 开启自动提交(系统默认设置)

综上:

-- 手动处理事务
-- 1.
SET autocommit = 0;  -- 关闭自动提交
-- 2.
-- 事务开启
START TRANSACTION;  -- 标记一个事务的开始,从这个之后的sql都在同一个事务内
-- 3.
INSERT XX
INSERT XX
-- 4.
-- 回滚 : 只要没COMMIT,就还可以滚回到的原来的样子 
ROLLBACK;
-- 提交 : 持久化(一旦提交,再回滚也滚不回去了)
COMMIT;
--5.
-- 事务结束
SET autocommit = 1; -- 开启自动提交

-- 补充:(了解)
SAVEPOINT 保存点名 -- 设置一个事务的保存点
ROLLBACK TO SAVEPOINT 保存点名 -- 回滚到保存点
RELEASE SAVEPOINT 保存点名 -- 撤销保存点

在这里插入图片描述

示例:(转账实现

-- 创建数据库:
CREATE DATABASE `shop` CHARACTER SET utf8 COLLATE utf8_general_ci; 
-- 创建数据表:
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
-- 插入数据
INSERT INTO `account`
VALUES(12,'小王',1000),(16,'小张',800)

-- 执行事务:
-- 1.关闭自动提交
SET autocommit = 0 
-- 2.开启事务
START TRANSACTION
-- 3.一组sql(虽然是一组sql,但也要挨个单句执行,多句执行应该可以,但现在是初学阶段)
UPDATE `account` SET `money` = `money` - 20 WHERE `name`='小王'
UPDATE `account` SET `money` = `money` + 20 WHERE `name`='小张'
-- 4.只要没COMMIT,就可以回滚;一旦提交,再回滚也滚不回去了
ROLLBACK
COMMIT
-- 5.恢复系统的默认设置
SET autocommit = 1

结果:
执行事务之前:
在这里插入图片描述
执行事务之后:
在这里插入图片描述
(只要没执行COMMIT,通过执行ROLLBACK是可以回到上上张图片的;一旦执行COMMIT,信息就永久更新,不可逆)

注意:(在实际应用中)

上面的示例只是手动去处理事务,在实际应用中,会把上面示例中的第3步和第4步放在一个try...catch...中,如果要执行的一组sql没有问题,能成功运行,就自动COMMIT,如果运行失败,相当于是异常情况,就跳到catch中自动回滚。
在这里插入图片描述

七、索引(index)

30,31小结

30主要讲了以下内容:

  • 啥是索引:是一种数据结构,用它可以快速找到数据。
  • 索引的分类:主键索引(只能有一个)、唯一索引、常规索引、全文索引。
  • 添加索引的三种方式:1.创建数据表的时候;2.用ALTER创建;3.用CREATE创建。
  • 删除索引DROP INDEX 索引名 ON 表名字;
  • 查看所有索引SHOW INDEX FROM 表名;
  • 然后用全文索引写了个例子,来说明有索引和没索引的区别:没索引就是整个数据表去搜索,有索引就是直接一下子找到。
    这里面用了关键字EXPLAIN查看sql执行的状况,相当于是个工具,可以查看这次查询一共用了多久的时间,查找了多少行数据

31中又写了一个例子,依然是全文索引

  • 把数据量增加到100万条
  • 用了一个函数mock_data(),先把这个函数写好;
  • 然后执行这个函数SELECT mock_data();
  • 然后又借助关键字EXPLAIN来说明加索引和不加索引的区别:不加索引,查一条数据要用1s多,加上索引再查这条数据只用0.01s

结论:索引在小数据量的时候,用处不大,但是在大数据的时候,优势十分明显

30.索引的 介绍、分类、添加、示例

索引的定义:

  • 索引(index)是帮助MySQL高效获取数据数据结构

索引的本质:

  • 索引是数据结构

索引的作用:

  • 提高查询速度
  • 确保数据的唯一性;
  • 可以加速表和表之间的连接 , 实现表与表之间的参照完整性;
  • 使用分组和排序子句进行数据检索时 , 可以显著减少分组和排序的时间;
  • 全文检索字段进行搜索优化。

索引的分类:

  • 主键索引(primary key):
    唯一的标识,主键的内容不可重复,且只能有一个列(字段)作为主键。
  • 唯一索引(unique key):
    避免出现重复的列名(字段名),可以有多个唯一索引,即可以将多个列标识为唯一索引。
  • 常规索引(key / index):
    默认的index 或者 key 关键字
  • 全文索引(FullText index):
    在特定的数据库引擎下才有,如MYISAM
    可以快速定位数据。

注意:主键索引只能有一个;唯一索引可以有多个。

添加所有的三种方式:
参考链接:数据库创建索引和删除索引的方式总结
1.创建表时给字段增加索引

-- 格式:
CREATE TABLE 表名 (
      字段名1 数据类型 [完整性约束条件…],
      字段名2 数据类型 [完整性约束条件…],
      [UNIQUE | FULLTEXT | PRIMARY]   INDEX/KEY
      [索引名] (字段名)
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 示例:
CREATE TABLE `result`(
   
  -- 省略一些代码
   
  PRIMARY KEY (`student_name`), -- 主键索引
  INDEX/KEY `ind` (`studentNo`,`subjectNo`), -- 常规索引
  UNIQUE KEY `UK_IDENTITY_CARD` (`identity_card`), -- 唯一索引
  FULLTEXT INDEX `FI_PHONE` (`phone`) -- 全文索引
)ENGINE=INNODB DEFAULT CHARSET=utf8

注意:因为主键索引是唯一的,所以不需要索引名,直接在括号里写字段名即可。
在这里插入图片描述
2.用ALTER在已建好的表上创建索引

-- 格式:
ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | ] INDEX/KEY
     索引名 (字段名)

-- 示例:
ALTER TABLE `student` ADD PRIMARY KEY (`student_name`); -- 主键索引
ALTER TABLE `result` ADD INDEX `ind`(`studentNo`,`subjectNo`); -- 常规索引
ALTER TABLE `student` ADD UNIQUE KEY `UK_IDENTITY_CARD` (`identity_card`); -- 唯一索引
ALTER TABLE `student`  ADD FULLTEXT INDEX `FI_PHONE` (`phone`); -- 全文索引

3.用CREATE在已建好的表上创建索引
语法:create index 索引名 on 表名(字段)

-- 格式:
CREATE [UNIQUE | FULLTEXT ] INDEX
     索引名 ON 表名 (字段名)

-- 示例:
CREATE INDEX `name` ON `student` (`studentname`);

注意:Create不能用于创建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`
-- 创建一个索引:
CREATE INDEX `name` ON `student` (`studentname`)
-- 删除索引:
DROP INDEX `name` ON `student`


-- 用explain来查看sql执行的状况,相当于是个工具,可以查看这次查询一共用了多久的时间,查找了多少行数据
-- 非全文索引:
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('张伟强');

示例所用到的数据表:
在这里插入图片描述
结果:
查看所有索引:
在这里插入图片描述

非全文索引:
在这里插入图片描述
在这里插入图片描述

添加全文索引:
在这里插入图片描述

全文索引:
在这里插入图片描述
在这里插入图片描述

解释下上面的全文索引
– 全文搜索通过 MATCH() 函数完成。
– 搜索字符串作为 against() 的参数被给定。搜索以忽略字母大小写的方式执行。对于表中的每个记录行,MATCH() 返回一个相关性值。即,在搜索字符串与记录行在 MATCH() 列表中指定的列的文本之间的相似性尺度。

-- 示例:
EXPLAIN SELECT *FROM student WHERE MATCH(studentname) AGAINST('love');

补充:
全文索引的版本、存储引擎、数据类型的支持情况:

  • MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引
  • MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
  • 只有字段的数据类型为 char、varchar、text 及其系列才可以创建全文索引;
  • 测试或使用全文索引时,要先看一下自己的 MySQL 版本、存储引擎和数据类型是否支持全文索引。

参考链接:
【MySQL优化】——看懂explain_漫漫长途,终有回转;余味苦涩,终有回甘-CSDN博客_explain

31. SQL编程创建100万条数据测试索引

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 '创建时间',
  `update_time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='app用户表'

2.批量插入100w条数据:(mock_data()是个函数)

DELIMITER $$ -- 写函数之前必须要写,标志
CREATE FUNCTION mock_data()
RETURNS INT
BEGIN
  DECLARE num INT DEFAULT 1000000;
  DECLARE i INT DEFAULT 0;
  WHILE i<num DO
    INSERT 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;

-- 执行函数
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

-- 创建索引:
-- 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

结果:
不加索引:
在这里插入图片描述
在这里插入图片描述

加索引:
在这里插入图片描述

在这里插入图片描述
查看索引信息:
在这里插入图片描述
在这里插入图片描述

结论:
索引在小数据量的时候,用处不大,但是在大数据的时候,区分十分明显。

32. 索引的 原则、数据结构

索引的原则:

  • 索引不是越多越好;
  • 不要对经常变动的数据加索引;
  • 小数据量的表建议不要加索引;
  • 索引一般应加在查找条件的字段。

索引的数据结构:

1.Hash类型的索引;
2.BTree(B树):INNODB引擎默认的数据结构;
3.全文索引。

– 我们可以在创建上述索引的时候,为其指定索引类型,分两类
hash类型的索引:查询单条快,范围查询慢
btree类型的索引:b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持它)

– 不同的存储引擎支持的索引类型也不一样
InnoDB 支持事务,支持行级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引;
Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引;
NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索引;
Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;

参考链接:MySQL索引背后的数据结构及算法原理

32’ 补充1: BTree索引(32中参考链接的内容)

摘要:
MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等。
为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论。

第一部分:数据机构及算法基础
数据库查询是数据库的最主要功能之一,我们都希望查询数据的速度能尽可能的快

常见的查询算法有

  • 顺序查找(linear search):这种复杂度为O(n)的算法在数据量很大时显然是糟糕的。
  • 二分查找(binary search):二分查找要求被检索数据有序
  • 二叉树查找(binary tree search):二叉树查找只能应用于二叉查找树上
    二叉查找树的改进:平衡二叉树(AVL树)+ 红黑树 -->见下面的 8.3 基于 树 的查找法 补充:红黑树和AVL树的详解和区别

在实际的数据库系统几乎没有使用二叉查找树或其进化品种红黑树(red-black tree)实现,因为数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织)。所以在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引(index)

目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构。

B树:(1)–>(2)–>(3)
(1)二叉排序树,又叫二叉查找树:

  • 若左子树为空,则左子树上所有结点的值均小于根结点的值;
    若右子树为空,则右子树上所有结点的值均大于等于根结点的值;
    左右子树也分别为二叉排序树。
  • 中序遍历一个二叉排序树可以得到一个递增有序序列

(2)m叉排序树,又叫m路查找树:

  • 一个结点最多有m棵子树,m-1个关键字;
  • 子树Pi中的所有关键字均大于Ki,小于K(i+1)
  • 子树P0中的关键字均小于K1,子树Pn中的所有关键字均大于Kn
  • 子树Pi也是m路查找树
  • 书本P289的例8.7
  • 在这里插入图片描述(3)B树,一颗平衡的m路查找树:
  • 每个结点做多有m棵子树;
  • 根结点至少有2棵子树;
  • 除根结点之外的所有非叶结点至少有ceiling(m/2)棵子树,ceiling(m/2) - 1个关键字;
  • 所有叶结点在同一层,也叫失败结点;
  • B树是“从叶向根”生长的,而根对每个分支是公用的,所以不论根长到多“深”,各分支的长度同步增长,因而各分支是“平衡”的
  • 书中P289的例8.8、8.9,—B树的基本性质
    P293的例8.10,8.11,—B树中插入一个关键字
    P296的例8.12,8.13,—B树中删除一个关键字

**B树**有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构。那么B树和B+树区别在哪?

参考链接1:简单剖析B树(B-Tree)与B+树
常说的B-树就是B树,没有所谓的B减树。
聚集索引(Clustered Index)、非聚集索引(NonClustered Index)、卫星数据?
B+树相比B树的优势:
  1.单一节点存储更多的元素,使得查询的IO次数更少;
  2.所有查询都要查找到叶子节点,查询性能稳定;
  3.所有叶子节点形成有序链表,便于范围查询。

参考链接2:B树和B+树
不同数据库引擎(MYISAM引擎和INNODB引擎)中B+树的差异:。

参考链接3:B树与B+树简明扼要的区别

参考链接4:面试总结:B树,B+树的原理及区别

参考链接5:面试题:B(B-)树,B+树,B树和B+树的区别,B树和B+树的优点

参考链接6:B树、B-树、B+树、B*树之间的关系

第二部分:MySQL索引实现:

  • MyISAM索引实现
  • InnoDB索引实现

第三部分:索引使用策略及优化

32’’ 补充2:数据结构教材的 第八章 查找算法

8.2 基于 线性表 的查找法

  • 顺序查找法:
  • 折半查找法:顺序存储、数据有序
  • 分块查找法:创建一个索引表,每个索引项记录一个块的起始位置和块中的最大关键字,索引表按关键字有序排列(即块之间有序,块内无序)。先用顺序查找或折半查找锁定块,然后在块内用顺序查找法。
    2

8.3 基于 树 的查找法

  • 二叉排序树:(二叉查找树)
    若左子树为空,则左子树上所有结点的值均小于根结点的值;
    若右子树为空,则右子树上所有结点的值均大于等于根结点的值;
    左右子树也分别为二叉排序树。
    中序遍历一个二叉排序树可以得到一个递增有序序列
  • 平衡二叉排序树:(AVL树)
    左右子树的高度之差的绝对值小于等于1;左右子树也是平衡二叉排序树。
    结点的平衡因子(Balance Factor)是指结点的左右子树深度之差,AVL树中所有结点的平衡因子只能是-1、0、1。
    给一个AVL树上插入一个结点,可能导致树失衡,失衡类型及相应的调整方法可归纳为四种:LL型、LR型、RR型、RL型
    红黑树和AVL树的区别:(见下面的详解)
  • B树:
    教材的P288 - P298,或者直接看上面的32’ 补充1:BTree索引
补充:红黑树和AVL树的详解和区别

(参考链接:红黑树和AVL树(平衡二叉树)区别链接2

AVL树是严格的平衡二叉树,一旦失衡就要通过旋转来保持平衡,而旋转是非常耗时的,因此AVL树适合用于插入与删除次数比较少,但查找比较多的情况。由于维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应用不多,更多的地方是用追求局部而不是非常严格整体平衡红黑树。当然,如果应用场景中对插入、删除不频繁,只是对查找要求较高,那么AVL还是较优于红黑树。

红黑树是一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是红或黑(非红即黑)。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍,因此,红黑树是一种弱平衡二叉树(由于是弱平衡,可以看到,在相同的节点情况下,AVL树的高度低于红黑树),相对于要求严格的AVL树来说,红黑树的旋转次数少插入,删除,查找的复杂度都是O(log N),所以对于搜索,插入,删除操作较多的情况下,就用红黑树。

红黑树的规则:

  • 规则1: 每个节点不是黑色就是红色(非红即黑);
  • 规则2: 根节点为黑色
  • 规则3:红色节点的父节点和子节点不能为红色;红色结点的两儿子都是黑的
  • 规则4:所有的叶子节点都是黑色(空节点视为叶子节点NIL);
  • 规则5任意一个节点到叶子节点的每条路径上黑色节点的个数都相等;
  • 规则6(特点):从根节点到叶子节点的最长的路径不多于最短的路径的长度的两倍

红黑树插入节点时的思路:(参考链接:红黑树与平衡二叉树区别?
插入的节点总是设为红节点,当其复节点为红节点时,这就有破坏了规则3,就需要调整。将插入节点作为考察节点,考察其叔父,如果也是红节点,则将其父亲和叔父改为黑节点,而将其祖父改为红节点,然后以其祖父为考察节点。如果其叔父是黑节点则做一旋转变换可以搞定,没有图不太好说明,你可以自己考虑一下,总之它的思想是把“多出来”的红色往上一层推去,确保下面层红黑性质,最后推到根以后,如果依然违反性质1,则可以直接把根由红改黑即可,就相当于把这“多出来”的红色推到树以外的节点去了。
删除节点时先要找到顶替的节点,如果删去的节点是黑色则破坏了规则5,也需要调整。调整的思想也同前面类似,把这个黑色赋予顶替节点,则顶替节点相当于有两重黑色,然后将它的两重黑色向上推,一直推到根,再从根推到外面去了。

平衡二叉树和红黑树的区别:

AVL树红黑树
概念严格的平衡二叉树,左右子树高度差的绝对值≤1弱平衡树,见上面的:红黑树的规则
失衡类型及相应的调整方法LL型、LR型、RR型、RL型见上面的红黑树插入节点时的思路
插入、删除因为要通过旋转来恢复平衡,代价高O(log N)
查找O(log N)O(log N)
应用适合用于插入与删除次数比较少,但查找比较多的情况
如果应用场景中对插入、删除不频繁,只是对查找要求较高,那么AVL还是较优于红黑树。
对于查找,插入,删除操作较多的情况下,就用红黑树;
广泛用于C++的STL中,map和set都是用红黑树实现的
左右自述的高度差绝对值小于等于1某些时刻可能会超过1,但红黑树确保没有一条路径会比其它路径长出两倍,只要符合红黑树的规则即可
失衡后的具体操作只要不平衡就会进行旋转改变颜色+旋转
是否是高度平衡是,严格的平衡二叉树否,弱平衡的二叉树,插入最多两次旋转,删除最多三次旋转

多余的内容:(不用看)

平衡二叉树和红黑树的区别:
+ 平衡二叉树的左右子树的高度差绝对值不超过1,
但是红黑树在某些时刻可能会超过1**红黑树确保没有一条路径会比其它路径长出两倍**,只要符合红黑树的五个条件即可;
+ 二叉树**只要不平衡就会进行旋转**,
而红黑树不符合规则时,**有些情况只用改变颜色不用旋转,就能达到平衡**+ AVL树适合用于**插入与删除次数比较少,但查找比较多**的情况,
对于**搜索,插入,删除操作较多的情况**下,就用**红黑树**+ AVL 树是**高度平衡的**,频繁的插入和删除,会引起频繁的reblance,导致效率下降,
红黑树不是高度平衡的,算是一种折中,插入最多两次旋转,删除最多三次旋转。

8.4 计算式查找法(哈希表)

八、权限管理和备份

33. 数据库用户管理

方式一:用SQLyog可视化管理用户

  • 添加用户;
  • 删除用户;
  • 管理用户权限(全局权限、对某个数据库的权限、对某个数据表的权限)

在这里插入图片描述
方式二:用sql命令管理用户
(首先找到用户表,在mysql数据库–>user数据表中)
sql命令对用户进行管理,实质上就是对用户表进行增删改查
在这里插入图片描述
创建用户、修改密码、重命名、用户授权、查看权限、撤销权限、删除用户

-- 创建用户:
-- 格式:CREATE USER 用户名 IDENTIFIED BY '密码'
CREATE USER lele IDENTIFIED BY '123456'
CREATE USER 'user_name'@'192.168.1.1' IDENTIFIED BY '123456'

-- 修改密码(修改当前用户密码):当前用户是root
SET PASSWORD = PASSWORD('654321'); -- 记得把密码改回来('123456')
-- 修改密码(修改指定用户密码):
SET PASSWORD FOR lele = PASSWORD('654321'); -- 记得把密码改回来('123456')
-- 修改密码:(数据库笔记1中的两条修改密码的命令行)
UPDATE mysql.user SET authentication_string=PASSWORD('123456') WHERE USER='root' AND HOST = 'localhost';
UPDATE USER SET PASSWORD=PASSWORD('123456')WHERE USER='root'; 修改密码

-- 重命名:
-- 格式:RENAME USER 原名字 TO 新名字;
RENAME USER lele TO lele2

-- 用户授权:
-- 格式:GRANT 权限列表 ON 数据库名.数据表名 TO 用户名
-- 给 用户lele2 授予 所有的库的所有的表 全部的权限ALL PRIVILEGES,
GRANT ALL PRIVILEGES ON *.* TO lele2
-- (解释:*.* 表示所有库的所有表; 库名.表名 表示某库下面的某表
-- 这里的 ALL PRIVILEGES 是除了给别人授权不行,其他都能干,
-- 即ALL PRIVILEGES指除了GRANT权限之外的所有权限)


-- 查看权限:
-- 查看当前用户的权限:
SHOW GRANTS; 或 SHOW GRANTS FOR CURRENT_USER; 或 SHOW GRANTS FOR CURRENT_USER();
-- 查看用户lele2的权限:(除GRANT权限之外的ALL PRIVILEGES)
SHOW GRANTS FOR lele2
-- 结果:GRANT ALL PRIVILEGES ON *.* TO 'lele2'@'%'
-- 查看root的权限:(有GRANT权限,和ALL PRIVILEGES)
SHOW GRANTS FOR root@localhost 
-- 结果:GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION

-- 撤销权限:(和授予权限正好相反)
-- 格式:REVOKE 权限列表 ON 数据库名.数据表名 FROM 用户名
REVOKE ALL PRIVILEGES ON *.* FROM lele2 --撤销用户lele2的所有权限
-- REVOKE ALL PRIVILEGES, GRANT OPTION FROM root -- 撤销root的所有权限
-- 不建议这么干!!!

-- 删除用户:
DROP USER lele2

授予权限的结果:
授予权限之前:
在这里插入图片描述

授予权限之后:(GRANT ALL PRIVILEGES ON *.* TO lele2
在这里插入图片描述

权限解释:

-- 权限列表
ALL [PRIVILEGES]    -- 设置除GRANT OPTION之外的所有简单权限
ALTER    -- 允许使用ALTER TABLE
ALTER ROUTINE    -- 更改或取消已存储的子程序
CREATE    -- 允许使用CREATE TABLE
CREATE ROUTINE    -- 创建已存储的子程序
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权限的表使用LOCK TABLES
PROCESS     -- 允许使用SHOW FULL PROCESSLIST
REFERENCES    -- 未被实施
RELOAD    -- 允许使用FLUSH
REPLICATION CLIENT    -- 允许用户询问从属服务器或主服务器的地址
REPLICATION SLAVE    -- 用于复制型从属服务器(从主服务器中读取二进制日志事件)
SELECT    -- 允许使用SELECT
SHOW DATABASES    -- 显示所有数据库
SHOW VIEW    -- 允许使用SHOW CREATE VIEW
SHUTDOWN    -- 允许使用mysqladmin shutdown
SUPER    -- 允许使用CHANGE MASTER, KILL, PURGE MASTER LOGS和SET GLOBAL语句,mysqladmin debug命令;允许您连接(一次),即使已达到max_connections。
UPDATE    -- 允许使用UPDATE
USAGE    -- “无权限”的同义词

GRANT OPTION    -- 允许授予权限


/* 表维护 */

-- 分析和存储表的关键字分布
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE 表名 ...
-- 检查一个或多个表是否有错误
CHECK TABLE tbl_name [, tbl_name] ... [option] ...
option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
-- 整理数据文件的碎片
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

34. MySQL备份

为什么要备份?

  • 保证重要的数据不丢失;
  • 数据转移。

MySQL数据库备份方法(三种方法)

  • 1.直接拷贝数据库文件和相关配置文件; – data文件夹(数据库笔记1中有提及)
  • 2.在sqlyog这种可视化工具中手动导出;-- 可视化操作
  • 3.使用命令行mysqldump导出 。 – 命令行

在sqlyog这种可视化工具中手动导出

在想要导出的表或者库中,右键:
在这里插入图片描述
注意下图中三处框起来的地方即可:
在这里插入图片描述

使用命令行mysqldump导出

导出:

-- 导出一张表 :
-- 格式:mysqldump -h主机 -u用户名 -p密码 数据库 表名 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql

-- 导出多张表 :
-- 格式:mysqldump -h主机 -u用户名 -p密码 数据库 表名1 表名2 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student result >D:/b.sql

-- 导出整个数据库 :
-- 格式:mysqldump -h主机 -u用户名 -p密码 数据库 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school >D:/c.sql

导入:
方式一:(推荐)

  • 登录
  • 切换到指定的数据库
  • 然后source 备份文件

(测试的时候可以先把school库中的student表备份下来a.sql,然后把student表删掉,然后按照上面的三个步骤导入)
在这里插入图片描述
方式二:(不推荐)
也可以这样:
mysql -u用户名 -p密码 库名 < 备份文件(要导入的文件)
在这里插入图片描述

九、规范数据库设计

35. 如何设计一个项目的数据库

为什么需要设计?
当数据库比较复杂的时候,我们就需要设计了。

糟糕的数据库设计:

  • 数据冗余,浪费空间;
  • 数据库插入和删除都会麻烦、异常(屏蔽使用物理外键);
  • 程序的性能差。

良好的数据库设计:

  • 节省内存空间;
  • 保证数据库的完整性;
  • 方便我们开发系统。

软件项目开发周期中数据库设计:

  • 需求分析阶段: 分析客户的业务和数据处理需求
  • 概要设计阶段:设计数据库的E-R模型图 , 确认需求信息的正确和完整.

设计数据库步骤:(个人博客)
第1步:收集信息
(与该系统有关人员进行交流 , 座谈 , 充分了解用户需求 , 理解数据库需要完成的任务)

  • 用户表(用户登录注销,用户的个人信息,写博客,创建分类)
  • 分类表(文章分类,谁创建的)
  • 文章表(文章信息)
  • 评论表
  • 友链表(友情链接信息)
  • 自定义表(系统信息,某个关键的字,或者一些主字段) key:value
  • 关注表(粉丝数)
  • 说说表(发表心情,字段: id…content…create_time)

第2步:标识实体[Entity]
(把需求落地到每个字段,数据库要管理的关键对象或实体,实体一般是名词,标识每个实体需要存储的详细信息[Attribute])

  • 用户表:
    在这里插入图片描述
  • 分类表:
    在这里插入图片描述
  • 文章表:
    在这里插入图片描述
  • 评论表:
    在这里插入图片描述
  • 友链表:

在这里插入图片描述

  • 关注表:
    在这里插入图片描述

第3步:标识实体之间的关系[Relationship]

  • 写博客:user --> blog
  • 创建分类:user --> category
  • 关注:user --> user
  • 友链:links
  • 评论:user --> user --> blog

博客,bbs,Ant Design

36.数据库的三大范式(了解)

问题 : 为什么需要数据规范化?
不合规范的表设计会导致的问题:

  • 信息重复;
  • 更新异常;
  • 插入异常:无法正确表示信息;
  • 删除异常:丢失有效信息。

三大范式:
第一范式 (1st NF):

  • 原子性:保证每一列不可再分

第二范式(2nd NF):

  • 前提:满足第一范式
  • 每张表只描述一件事情

第三范式(3rd NF):

  • 前提:满足第一范式和第二范式
  • 第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关

三大范式是用来规范数据库的设计,但存在规范性和性能的问题(不可兼得的关系):
(阿里有句话:关联查询的表不得超过三张表

  • 考虑商业化的需求和目标(成本,用户体验)时,数据库的性能更加重要
  • 在规范性能的问题的时候,需要综合考虑一下规范性;
  • 有时会故意给某些表增加一些冗余的字段(从多表查询中变为单表查询),以大量减少需要从中搜索信息所需的时间;
  • 有时会故意增加一些计算列(从大数据库降低为小数据量的查询:索引)。

十、JDBC(重点)

37. 数据库驱动 和 JDBC

1.数据库驱动
驱动:声卡、显卡、数据库

应用程序 通过 数据库驱动数据库 打交道。
在这里插入图片描述

2.JDBC
UN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范,俗称JDBC

这些规范的实现由具体的厂商去做~
对于开发人员来说,我们只需要掌握JDBC接口的操作即可!

在这里插入图片描述

38-44

在这里插入图片描述

45. 数据库连接池

数据库连接 – 执行完毕 – 释放 整个过程中 连接-- 释放 是十分浪费系统资源的,所以就有了

池化技术:准备一些预先的资源,过来就连接预先准备好的。

最小连接数:10(常用连接数)
最大连接数:100 (业务最高承载上线)
等待超时:100ms(等待超过100ms就会告诉客户这里发生异常,让客户找别家)

编写连接池,实现一个接口DataSource。

总结:无论用什么数据源,本质还是一样的,DataSource接口不会变,方法就不会变。

(数据库的课先学到这,2022-04-15 21:44:26)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值