- 目录:
- 多表简介
- SQL 约束-外键约束
- 多表关系简介
- 多表查询
- 多表查询-内连接查询
- 多表查询-外连接查询
- 子查询简介
- 子查询实战
- 数据库进阶
- redis 内存数据库
- mongodb nosql 数据库
- neo4j 图数据库
1.多表简介
多表及使用场景介绍:
- 多表顾名思义就是在数据库设计中使用多张表格来实现数据存储的要求
- 在实际的项目开发中,数据量大而且复杂,需要分库分表
- 分表:按照一定的规则,对原有的数据库和表进行拆分
- 表与表之间可以通过外键建立连接
多表设计案例:
假定我们现在需要创建一张员工信息表,包含字段:
- eid 员工ID (自增主键)
- ename 员工姓名
- age 年龄
- gender 性别
- dept_name 所在部门
- dept_id 部门ID
- dept_manager 部门主管
- dept_location 所在地点
以单表的形式完成建表:(创建员工信息表)
CREATE TABLE emp(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(20),
age INT ,
gender VARCHAR(10),
dept_name VARCHAR(20),
dept_id INT,
dept_manager VARCHAR(20),
dept_location VARCHAR(20)
);
插入数据:
INSERT INTO emp VALUES (1,'张三', 20, '男','研发部',1,'张无忌','北京');
INSERT INTO emp(ename, age,gender,dept_name,dept_id,dept_manager, dept_location) VALUES ('李四', 25, '男','研发部',1,'张无忌','北京');
INSERT INTO emp(ename, age,gender,dept_name,dept_id,dept_manager, dept_location) VALUES ('宋江', 40, '男','研发部',1,'张无忌','北京');
INSERT INTO emp(ename, age,gender,dept_name,dept_id,dept_manager, dept_location) VALUES ('林冲', 25, '男','研发部',1,'张无忌','北京');
INSERT INTO emp(ename, age,gender,dept_name,dept_id,dept_manager, dept_location) VALUES ('林徽因', 25, '女','研发部',1,'张无忌','北京');
INSERT INTO emp(ename, age,gender,dept_name,dept_id,dept_manager, dept_location) VALUES ('周芷若', 25, '女','运营部',2,'赵敏','深圳');
INSERT INTO emp(ename, age,gender,dept_name,dept_id,dept_manager, dept_location) VALUES ('任盈盈', 25, '女','运营部',2,'赵敏','深圳');
单表数据冗余:
多表设计模式:
- 将数据拆分为员工信息表employee和部门信息表dept
- 两个表之间通过部门id:dept_id字段连接
# 创建员工信息表
CREATE TABLE emp_part(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(20),
age INT ,
gender VARCHAR(10),
dept_id INT
);
# 创建部门表
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(20),
dept_manager VARCHAR(20),
dept_location VARCHAR(20)
);
# 向部门表插入数据
INSERT INTO dept(dept_name,dept_manager,dept_location) VALUES('研发部','张无忌','北京');
INSERT INTO dept(dept_name,dept_manager,dept_location) VALUES('运营部','赵敏','深圳');
# 向员工信息表插入数据
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('李四', 25, '男',1);
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('宋江', 40, '男',1);
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('张三', 20, '男',1);
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('林冲', 25, '男',1);
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('林徽因', 25,'女',1);
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('周芷若', 25,'女',2);
INSERT INTO emp_part(ename,age,gender,dept_id) VALUES ('任盈盈', 25, '女',2);
多表关系:
多表的优点:
- 简化数据
- 提高复用性
- 方便权限控制
- 提高系统的稳定性和负载能力
2.SQL 约束-外键约束
外键约束的定义与意义:
-
主键:可以唯一标识一条记录的列
-
外键:从表中与主表的主键对应的字段
-
主表:外键所指向的表,约束其他表的表
-
从表:外键所在的表,被约束的表
-
价值:建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性
建立外键约束:
-
创建表时添加外键约束:
CONSTRAINT [外键约束的名称] FOREIGN KEY (外键字段) REFERENCES [主表名称(主键字段)]
-
添加外键约束:
ALTER TABLE [表名] ADD CONSTRAINT [外键约束的名称] FOREIGN KEY [外键字段] REFERENCES [主表名称(主键字段)]
# 创建一个关联到主表的从表
CREATE TABLE emp_part(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(20),
age INT ,
gender VARCHAR(10),
dept_id INT,
-- 添加外键约束
CONSTRAINT emp_dept FOREIGN KEY(dept_id) REFERENCES dept(id)
);
# 插入一条非法数据
INSERT INTO emp_part VALUES(1,'cindy',20,'female','4')
删除外键约束:
- 语法:
ALTER TABLE [表名] DROP FOREIGN KEY [外键约束名称]
- 注意事项
- 从表外键数据类型必须与主表的主键一致
- 删除数据时,需先删除从表数据再删除主表的数据
- 添加数据时先添加主表数据,再添加从表数据
# 删除外键约束
ALTER TABLE emp_part DROP FOREIGN KEY emp_dept
# 插入一条非法数据
INSERT INTO emp_part VALUES(1,'cindy',20,'female','4')
SELECT * FROM emp_part
# 向主表中插入一条数据
INSERT INTO dept VALUES(2,'运营部','张三','北京')
# 向从表中插入一条数据
INSERT INTO emp_part VALUES(1,'cindy',20,'female','2')
# 删除主表中的数据
DELETE FROM dept WHERE id=2
级联删除:
- 删除主表数据的同时,也删除掉从表中相关的数据
- ON DELETE CASCADE
创建员工信息表并添加级联删除的外键约束:
CREATE TABLE emp_part(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(20),
age INT ,
gender VARCHAR(10),dept_id INT,
– 添加外键约束
CONSTRAINT emp_dept FOREIGN KEY(dept_id) REFERENCES dept(id)
– 设置允许级联删除
ON DELETE CASCADE
);
# 向员工信息表中添加一条数据
INSERT INTO emp_part VALUES(1,‘cindy’,20,‘female’,‘2’)
#删除主表中部门id=2的部门
DELETE FROM dept WHERE id=2
# 查看从表中的数据是否同时被删除
SELECT * FROM emp_part
3.多表关系简介
一对多:
- 定义: 主表的一条记录可以对应从表的多条记录
- 例子: 部门表,员工表
- 建表原则:在一对多关系中,多的表定位从表,设置外键指向主表
多对多:
- 定义:主表的多条记录可以对应从表的多条记录
- 例子:商品信息表,客户表,订单表
- 建表原则:需要创建第三张表作为中间表,中间表需要包含两张表的主键。
一对一:
- 定义:从表的一条记录对应主表的一条记录
- 例子:员工信息表与身份证表,联系方式
- 建表原则: 这种对应关系的数据,通常放在单表里
4.多表查询
多表查询的定义:
- 定义: 通过查询多张表格获取数据,至少涉及两张表
- 数据准备:
- 创建部门表,插入三条数据
- 创建员工信息表添加外键约束,允许级联删除,并向三个部门插入对应的员工信息
## 创建部门信息表
CREATE TABLE dept(
id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(20),
dept_manager VARCHAR(20),
dept_location VARCHAR(20)
);
INSERT INTO dept VALUES(1,'研发部','张无忌','北京');
INSERT INTO dept VALUES(2,'运营部','赵敏','深圳');
INSERT INTO dept VALUES(3,'销售部','周芷若','成都');
# 创建员工信息表并添加级联删除的外键约束
CREATE TABLE emp_part(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
ename VARCHAR(20),
age INT ,
gender VARCHAR(10),
dept_id INT,
salary INT,
-- 添加外键约束
CONSTRAINT emp_dept FOREIGN KEY(dept_id) REFERENCES dept(id)
-- 设置允许级联删除
ON DELETE CASCADE
);
向员工信息表中插入数据:
INSERT INTO emp_part VALUES(1,'令狐冲',25,'男','1',20000);
INSERT INTO emp_part VALUES(2,'任盈盈',23,'女','1',15000);
INSERT INTO emp_part VALUES(3,'岳不群',45,'男','1',40000);
INSERT INTO emp_part VALUES(4,'任我行',40,'男','1',30000);
INSERT INTO emp_part VALUES(5,'岳灵珊',21,'女','1',10000);
INSERT INTO emp_part VALUES(6,'赵灵儿',21,'女','2',7000);
INSERT INTO emp_part VALUES(7,'林月如',22,'女','2',10000);
INSERT INTO emp_part VALUES(8,'阿奴',20,'女','2',7000);
INSERT INTO emp_part VALUES(9,'李逍遥',25,'男','2',15000);
INSERT INTO emp_part VALUES(10,'景天',28,'男','2',20000);
INSERT INTO emp_part VALUES(11,'邱莹莹',21,'女','3',5000);
INSERT INTO emp_part VALUES(12,'关雎尔',22,'女','3',8000);
INSERT INTO emp_part VALUES(13,'曲筱绡',23,'女','3',10000);
INSERT INTO emp_part VALUES(14,'樊胜美',30,'女','3',10000);
INSERT INTO emp_part VALUES(15,'安迪',28,'女','3',20000);
笛卡尔积:
-
定义: 笛卡尔积是一个数学概念,又称直积,它是指两个集合元素所有可能有序对的集合。
-
例子:
A={a,b},B={c,d}
A*B ={(a,c),(b,c),(a,d),(b,d)}
-
语法:select 字段名称 from 表1, 表2
查询出运营部的部门信息及该部门下的员工信息
select * from dept,emp_part where dept.id=emp_part.dept_id and dept.id=2;
5.多表查询-内连接查询
内连接的定义:
- 内连接(INNER JOIN):使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行,组合成新的记录。匹配上显示,匹配不上不显示。
- 例子: 比如使用外键=主键这个条件过滤掉无效数据
- 按语法结构分为: 隐式内连接和显式内连接
隐式内连接:
-
在笛卡尔积的的基础上,使用where条件过滤无用的数据,这种连接方式是隐式内连接.
-
语法:select [字段名称] from 表1,表2 where [条件]
-
例1: 筛选出运营部的员工的id,姓名以及所在城市
SELECT emp_id,ename,dept_location FROM emp_part,dept WHERE dept_id=id and dept_name="运营部";
显式内链接:(注意inner关键字可以省略)
- 显式内连接: 使用 select [字段名称] from [表1]inner join [表2] on [条件] 这种方式
- 列子: 用显式内连接查询运营部的员工的id,姓名以及所在城市
SELECT emp_id,dept_location,ename FROM emp_part INNER JOIN dept ON dept_id=id AND dept_name="运营部"
6.多表查询-外连接查询
外连接介绍:
-
外连接查询:查询多个表中相关联的行,有时候需要包含没有关联的行中数据,即返回查询结果集合中不仅包含符合连接条件的行,还包括左表(左连接)、右表(右连接)中的所有数据行。
-
左外连接 , 使用 LEFT OUTER JOIN , OUTER 可以省略
-
右外连接 , 使用 RIGHT OUTER JOIN , OUTER 可以省略
左连接:
-
左连接:以左表为基准匹配右表的数据,右表中没有的项,显示为空
-
语法:SELECT [字段] FROM [左表] LEFT JOIN [右表] ON [条件]
-
例子:公司新成立人力资源部,还未招聘员工,请使用左连接查询方式查询出公司所有部门员工的员工号,姓名,性别以及他们所在的部门名称和城市
#向部门表中插入人力资源部
INSERT INTO dept VALUES(4,'人力资源部','甄嬛','北京');
#使用左连接查询方式查询出公司所有部门员工的员工号,姓名,性别以及他们所在的部门名称和城市
SELECT emp_id,ename,gender,dept_name,dept_location FROM dept LEFT JOIN emp_part ON dept.id=emp_part.dept_id
右连接:
-
右连接:以右表为基准匹配左表的数据,左表中没有的项,显示为空
-
语法:SELECT [字段] FROM [左表] RIGHT JOIN [右表] ON [条件]
-
使用右连接的方式查询出所有员工信息以及他们所在的部门名称和城市
insert into emp_part (ename,age,gender,salary) values ('Tom',26,'male',5000);
#使用右连接的方式查询出所有员工信息以及他们所在的部门名称和城市
select emp_id,ename,age,gender,salary,dept_name,dept_location from dept right join emp_part on id=dept_id;
总结:
- 内连接: inner join
- 左连接: left join
- 右连接: right join
- 内连接和左连接使用居多
7.子查询简介
-
定义:子查询指一个查询语句嵌套在另一个查询语句内部,在SELECT子句中先计算子查询,子查询的结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。 这个特性从MySQL 4.1开始引入。
-
子查询作为过滤条件时需要用
()
包裹
子查询的常见分类:
- From型子查询:将子查询的结果作为父查询的表来使用
- in/not in 型子查询:子查询的结果是单列多行,作为where的过滤条件
- where型子查询:查询结果作为过滤条件出现在比较运算符的一端
带From关键字的子查询:
- 子查询是一张多行多列的表,将子查询作为父查询的表来嵌套查询
- 子查询语句必须用()包裹且需要有别名
- 计算出各部门性别为男性的员工人数
select dept_name,count(emp_id) from (select dept_name, emp_id,ename,gender from dept inner join emp_part where id=dept_id and gender='男')b group by dept_name;
带IN关键词的子查询:
- 将子查询作为where语句后的过滤条件,常用于子查询结果是单列多行的情况
- 子查询语句必须用()包裹
- in/not in
- 查询出北京地区所有的员工信息
SELECT * FROM emp_part WHERE dept_id IN (SELECT id FROM dept WHERE dept_location = '北京')
带比较运算符的子查询
- 将子查询的结果作为过滤条件,放在比较运算符的一端
- 常用于子查询结果为单个结果的情况
- 子查询语句必须用()包裹
#查询出薪资大于公司平均薪资的员工id,姓名及薪资
SELECT emp_id,ename,salary FROM emp_part WHERE salary > (SELECT AVG(salary) FROM emp_part);
with…as
-
如果一整句查询语句中,某个子查询的结果会被多个父查询引用,通常建议将共用的子查询用简写表示出来
-
语法: with [表名] as (select…)
# 查询出部门平均薪资大于公司平均薪资的部门名称,部门主管,所在地及部门平均薪资
# 不使用 with ...as
select dept_id,dept_name,dept_manager,dept_location,avg_salary from dept inner join (select dept_id,avg(salary) avg_salary from emp_part group by dept_id)b on id=dept_id and avg_salary > (select avg(avg_salary) from (select dept_id,avg(salary) avg_salary from emp_part group by dept_id)b);
# 使用 with ...as
with dept_avg as (select dept_id,avg(salary) avg_salary from emp_part group by dept_id)select dept_id,dept_name,dept_manager,dept_location,avg_salary from dept inner join dept_avg on id=dept_id and avg_salary > (select avg(avg_salary) from dept_avg);
8.子查询实战
项目介绍:
- A公司是一家软件产品销售公司,在北京,上海,深圳,成都,杭州都设有销售部门,其中销售部门分布如下:
- 北京有3个销售部门,分别为bj001,bj002,bj003
- 上海有三个销售部门为:sh001,sh002,sh003
- 深圳有两个销售部门为:sz001,sz002
- 成都有一个销售部门为:cd001
- 杭州有一个销售部门为:hz001
- department表中记录了部门相关的信息
- sales_list表中记录了最近2周各部门的销售订单相关数据
项目需求:
- 需求1:在mysql中创建数据库test_db1 并导入相关数据
- 需求2:计算出各部门最近两周的的总销售业绩,并按业绩由高到低显示
- 需求3:查询出最近两周的销售额超过全公司平均销售额的部门
创建数据库并导入相关数据:
- 部门表字段
- dept_id 部门id
- city 所在城市
- manager 部门经理
- 订单表
- dept_id 部门id
- order_id 订单号
- volume 客单价
- sales_date 销售日期
# 计算出各部门最近两周的总业绩,并按业绩由高到低排名
SELECT order_list.dept_id, city, manager, SUM( volume ) total_volume FROM order_list INNER JOIN department ON order_list.dept_id = department.dept_id GROUP BY order_list.dept_id ORDER BY SUM( volume ) DESC
#查询出最近两周销售额超平均销售额的部门
WITH temp_dept AS ( SELECT order_list.dept_id, city, manager, SUM( volume ) total_volume FROM order_list INNER JOIN department ON order_list.dept_id = department.dept_id GROUP BY order_list.dept_id ORDER BY SUM( volume ) DESC ) SELECT * FROM temp_dept WHERE total_volume >( SELECT AVG( total_volume ) FROM temp_dept)
视图:
- 定义:视图是一种虚拟的表,它并不会在你的存储空间复制一份数据,而是对原有数据的一种引用。可以将视图理解为一种存储起来的sql语句
- 视图可以简化多表查询
- 视图也可以用于控制用户权限
- 使用关键词view来创建视图
- 语法:CREATE VIEW [视图名称] AS SELECT…..
CREATE VIEW temp_dept AS ( SELECT order_list.dept_id, city, manager, SUM( volume ) total_volume FROM order_list INNER JOIN department ON order_list.dept_id = department.dept_id GROUP BY order_list.dept_id ORDER BY SUM( volume ) DESC );
SELECT * FROM temp_dept WHERE total_volume >( SELECT AVG( total_volume ) FROM temp_dept);
#查询出最近两周的冠军销售部门
SELECT * FROM temp_dept WHERE total_volume=(SELECT max(total_volume) FROM temp_dept);
9.数据库进阶
MySQL中 SQL执行原理:
- 客户端向MySQL服务器发送SQL语句。
- MySQL服务器接收到SQL语句后,将其解析成一个语法树。
- MySQL服务器根据语法树生成一个查询计划。
- MySQL服务器根据查询计划选择合适的存储引擎,并将数据从存储引擎中读取出来。
- MySQL服务器将读取的数据进行优化,包括常量折叠、去重、排序等操作。
- MySQL服务器将优化后的数据发送给客户端。
- 客户端接收到数据后,进行进一步处理,如显示、保存等操作。
SQL语句执行过程:
Server组件:
- 连接器:负责管理客户端连接,验证用户权限,并提供安全访问服务。连接器与优化器配合,为每个连接生成唯一的执行计划,以确保最佳的性能和安全性。
- 查询缓存:负责缓存查询结果,以便在相同或相似的查询中直接返回结果,提高查询效率。
- 分析器:负责将用户输入的SQL语句进行语法分析,检查语句的正确性和规范性,生成语法树。
- 优化器:负责分析语法树,生成优化的执行计划,选择最合适的索引和执行方式,以提高查询效率。
- 执行器:负责执行优化后的执行计划,对数据进行处理和操作,如读取、写入、更新等操作,并返回结果。
索引
- 索引是存储的表中一个特定列的值数据结构
- 索引包含一个表中列的值,并且这些值存储在一个数据结构中
索引分类:
- 单列索引
- 普通索引
- 唯一索引:允许NULL值
- 主键索引:不允许NULL值
- 组合索引
- 全文索引
- 单列索引是指在一个表中只针对一个列或少数列创建的索引。单列索引可以加速对单个列的查询,但是会降低对其他列的查询性能。
- 普通索引是单列索引的扩展,可以在多个列上创建索引,索引的数据结构可以是B-tree或哈希表等。普通索引可以加速对多个列的查询,但是同样会影响对其他列的查询性能。
- 唯一索引可以确保索引列中的每个值都是唯一的,不允许出现相同的值。唯一索引可以加速对唯一值的查询,但是同样会影响对其他列的查询性能。唯一索引通常用于主键索引和其他需要唯一性的列上。
- 主键索引是一种特殊的唯一索引,它用于唯一标识表中的每一行数据。主键索引通常由一个或多个列组成,用于确保每一行数据的唯一性。主键索引不允许出现NULL值,因为NULL值无法唯一标识一行数据。
- 组合索引是由多个列组成的索引,通常用于加速对多个列的查询。组合索引可以加速对所有列的查询,但是同样会影响对其他列的查询性能。
- 全文索引是一种特殊的索引,用于加速对文本数据的全文搜索。全文索引通常由一个或多个列组成,用于对文本数据进行分词、索引和搜索。全文索引可以提高对文本数据的搜索性能,但是同样会影响对其他列的查询性能。
索引优点:
- 提高数据检索的效率,降低数据库的IO成本
- 通过索引对数据进行排序,降低数据排序的成本,降低了CPU的消耗
索引缺点:
- 占用空间
- 降低更新表的速度
- 需要花时间研究建立最优秀的索引,或者优化
索引适合的场景:
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该创建索引
- 查询中与其他表关联的字段,外键关系建立索引.
- 查询中排序的字段
explain
- 模拟优化器执行SQL查询语句
- 分析查询语句或是表结构的性能瓶颈
explain使用:
explain + SQL语句
- id:表示查询优化器执行的查询计划中的每个步骤的唯一标识符。
- select_type:表示查询的类型,如SELECT、INSERT、UPDATE、DELETE等。
- table:表示查询中使用的表的名称。
- type:表示查询优化器如何处理表,包括系统表、索引、连接等。
- possible_keys:表示查询中可能使用的索引,如果没有使用索引,则该列将为NULL。
- key:表示实际使用的索引,如果没有使用索引,则该列将为NULL。
- key_len:表示实际使用的索引的长度,即索引中唯一值的数量。
- ref:表示查询中实际引用的列或表,如果没有引用任何列或表,则该列将为NULL。
- rows:表示查询将返回的行数。
- Extra :表示有关查询执行计划的其他信息,如是否使用临时表、是否进行子查询等。
explain 作用:
- 表的读取顺序
- 数据读取操作的操作类型
- 哪些索引可以使用
- 哪些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
事务:
- 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。
- 事务由事务开始与事务结束之间执行的全部数据库操作组成。
事务特点-ACID:
- 原子性(Atomicity):事务是一个原子性操作,要么全部执行,要么全部不执行,具有原子性。
- 一致性(Consistency):事务执行后,数据库的状态必须是一致的。这意味着事务执行之前和之后,数据库的状态必须是一致的,即事务执行期间不能出现违反数据完整性的情况。
- 隔离性(Isolation):多个事务同时执行时,它们之间相互隔离,互不影响。即同一时间只能有一个事务对数据库进行修改,其他事务必须等待该事务执行完毕才能执行。
- 持久性(Durability):事务一旦提交,其结果就是永久性的,即对数据库的修改是永久有效的。即使发生系统故障或重启,也不会影响已经执行的事务。
事务操作:
- begin开始一个事务
- rollback事务回滚
- commit事务提交
日志:
- slow log:慢查询日志,超出预设的long_query_time阈值的SQL记录
- general log:全局查询日志,所有SQL查询的记录
查看慢查询日志:
- 查看日志开关: show variables like '%query%';
- 打开日志开关: set global slow_query_log='ON';
- 设置阈值: set long_query_time=0.01;
- 执行SQL语句
- 查看日志内容
在表中查看日志:
- 修改日志存放方式: set global log_output = 'table';
- 查看表中内容: select * from mysql.slow_log;
查看全局查询日志:
- 查看变量信息: show variables like '%general%';
- 打开日志开关: set global general_log = 'ON';
- 执行SQL语句
- 查看表中日志内容: select * from mysql.general_log;
10.redis 内存数据库
Redis简介:
- redis:完全开源免费的高性能的key-value数据库。
- 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用;
- 不仅仅支持简单的kev-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储;
- 支持数据的备份,即master-slave模式的数据备份;
- 性能极高,Redis能读的速度是110000次/s,写的速度是81000次/s;
- Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来;
- 支持publish/subscribe,通知, key过期等等特性。
windows10安装下载redis :
Releases · microsoftarchive/redis · GitHub
将下载好的文件解压,将文件夹重新命名为Redis,此文件只需解压无需安装
基本数据结构:
- String:是二进制安全的,意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象;最大能存储512MB。
- Hash:一个string类型的key和value的映射表,hash特别适合用于存储对象;存储232-1键值对(40多亿).
- List:按照插入顺序排序,你可以添加一个元素到列表的头部(左边〉蚁有尾类〈边)。可存储232-1元素(每个列表可存储40多亿)
- Set:无序集合,通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
- Sorted Set:有序集合每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序;zset的成员是唯一的,但分数(score)却可以重复。
各个数据类型应用场景:
基本使用:
String: SET ky member/GET key
Hash: HMSET key field1 "Hello" field2"World"/HGET/HGETALL keyfield1
List: lpush key member/lrange key 0 10
Set: sadd key member/smembers key
Sorted Set: zadd key score member/ZRANGEBYSCORE key 0 1000
11.mongodb nosql 数据库
关系型数据库:
- MySql, Orcale, SqlServer,Access...
- SQL(结构化查询语言)
关系型数据库的优点:
- 数据一致性:关系型数据库通过引入表和列的概念,建立了严谨的数据一致性,使得数据的插入、删除和更新等操作都受到了控制,从而保证了数据的一致性。
- 查询性能:关系型数据库的查询性能相对较高,因为它们使用索引来提高查询效率,同时支持复杂的查询语言,如SELECT、WHERE、GROUP BY、ORDER BY等。
- 安全性:关系型数据库提供了较高的安全性,支持权限控制和加密技术,以保护数据免受未授权的访问和篡改。
- 扩展性:关系型数据库的扩展性较好,可以通过增加硬件和调整配置来提高性能和容量。
关系型数据库的缺点:
- 数据冗余:关系型数据库为了保持数据的一致性,通常需要将数据存储在多个表中,这可能导致数据冗余的问题。
- 复杂查询:由于关系型数据库使用表和列的概念,查询语句可能会变得复杂,对于复杂的查询操作,可能需要编写较为复杂的SQL语句。
- 事务处理:关系型数据库不支持原子性操作,需要使用事务处理来保证数据的一致性和可靠性。
- 索引维护:关系型数据库使用索引来提高查询效率,但索引的维护成本相对较高,对于大规模的数据操作,索引的更新和维护可能会影响性能。
非关系型数据库优点:
- 灵活性:非关系型数据库的数据结构比较灵活,可以支持任意数据结构,因此对于复杂的数据存储和处理更为适合。
- 易于扩展:非关系型数据库通常支持水平扩展和垂直扩展,可以轻松地增加存储空间和处理能力。
- 易于学习和使用:非关系型数据库通常使用较为流行的编程语言和框架,学习成本相对较低。
- 实时性:非关系型数据库通常具有较高的实时性,可以快速响应数据查询和更新操作。
- 快速开发:非关系型数据库通常具有较为完善的数据模型和查询语言,可以快速开发数据存储和查询功能。
非关系型数据库缺点:
- 事务隔离能力不足:虽然非关系型数据库也支持并发访问,但是由于其数据结构简单,没有提供事务的隔离级别,因此并发能力有限。
- 事务处理能力不足:由于非关系型数据库没有提供事务处理的功能,因此需要使用第三方工具来实现事务处理,这会增加开发成本和复杂性。
- 查询语言不够灵活:非关系型数据库通常使用简单的查询语言,如MongoDB的查询语言,不支持复杂的查询操作,因此查询效率较低。
- 无法进行数据规范化:由于非关系型数据库的数据结构简单,无法进行数据规范化,因此无法像关系型数据库一样进行规范化设计。
- 无法进行数据统计:由于非关系型数据库的数据结构简单,无法进行数据统计,因此无法像关系型数据库一样进行数据统计操作。
关系型数据库与非关系型数据库对比:
MongoDB:
- 非关系型数据库nosql
- 文档存储:类json格式
- 有机会对字段建立索引,实现关系数据库
下载安装:MongoDB下载安装教程_mangdb怎么下_小码哥呀的博客-CSDN博客
MongoDB操作:
删除数据库:
- 查看当前数据库
- show dbs
- 切换数据库(如果没有会自动创建)
- use demo1
- 往数据库中插入一条数据
- db.demo1.insert({"name":“小红"})
- 切换数据库
- use demo1
- 删除数据库
- db.dropDatabase()
什么是集合?
- 集合相当于一张表
- 集合可以有多个文档
创建/查看/删除集合:
- 创建集合
- db.createCollection('collection1')。
- 查看已经创建的集合
- show collections。
- 删除集合
- db.collection1.drop()
- db.collection1.drop()
插入和查看文档:
插入文档:
- 文档是mongodb中的基本单元
- 相当于表中的一条记录
- 以json格式显示
插入/查看文档:
- 插入文档时,MongoDB自动创建集合
- db.collectionDemo.inset("name" : "hello"})
- 查看插入的内容
- db.collectionDemo.find().pretty()
插入复杂文档:
声明变量,插入文档
document=({
title: 'MongoDB',
by: 'RuotongYu',
tags: ['mongodb', 'database', 'NoSQL']
});
db.collectionDemo.insert(document)
修改和删除文档:
格式:
db.collection.update(
<query>,
<update>,{
upsert: <boolean>,multi:<boolean>,
writeConcern: <document>}
)
可选选项:
- upsert :如果不存在update的记录,是否插入,默认false
- multi:把按条件查出来多条记录全部更新,默认fasle
- writeConcern:抛出异常的级别。
修改文档:
- 修改文档
- db.col.update({'title"':'MongoDB'},
- {'title':'MongoDB123'})
- 修改多个文档
- db.col.update({'name"':'hello'}
- {$set:{'name":hello123'3},
- {multi:true})
注意:update是替换,没有修改的字段会消失!
删除多个文档
- 删除多个文档
- db.col.remove({'name':'hello123'})
- 删除一个文档
- db.col.remove({'name':'hello'},1)
$inc
- 用法:{$inc:{field:value}}
- 作用:对一个数字字段的某个field增加value
- 示例:将name为xiaohong的学生的age增加5
- db.students.update({name:"xiaohong"},{$inc:{age:5}})
$set
- 用法:{$set:{field:value}}
- 作用:把文档中某个字段field的值设为value
- 示例:把xiaohong的年龄设为10岁
- db.students.update({name:"xiaohong "},{$set:{age:10}})
$unset
- 用法:{$unset:{field:1}}
- 作用:删除某个字段field
- 示例:将chenzhou的年龄字段删除
- db.students.update({name:"chenzhou"},{$unset:{age:1}})
$push
- 用法:{$push:{field:value}}
- 作用:把value追加到field里。注: field只能是数组类型,如果field不存在,会自动插入一个数组类型
- 示例:给chenzhou添加别名"michael"
- db.students.update({name:"chenzhou"}, {$push:{"ailas":"Michael"")
$rename
- 用法:{$rename:{old_field_name:new_field_name}}。
- 作用:对字段进行重命名
- 示例:把xiaohong记录的name字段重命名为hello
- db.students.update({name:"xiaohong"},{$rename:{ "name":"hello"]})
12.neo4j 图数据库
定义:
Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中
Neo4j特点:
- 非关系型数据库
- NoSql
- CQL
- 遵循SQL语法,简单,且人性化
安装与使用 超详细neo4j安装教程_至少我有我a的博客-CSDN博客
启动:在命令行处输入neo4j.bat console
创建节点:
创建标签节点:
- 打开浏览器
- 创建emp节点,标签为Enployee
- create(emp:Employee)
- 创建XiaoHong节点,带有属性
- CREATE(XiaoHong:People {no:1,age:10,gender:"M"})
添加属性
创建带属性的节点:
CREATE (book:Book {title:"book1",pages:340,price:250})
添加属性:
- match (book{title:"book1"})
- set book.name = "hello"
- return book
查询
检索节点的age属性
- MATCH需要与RETURN一起使用
- MATCH (XiaoHong:People)
- RETURN XiaoHong.age
关系:
创建关系
CREATE (p1:Profile1)-[r1:LIKES]->(p2:Profile2)
删除节点和关系
删除相应属性下的节点
MATCH (e: People) DELETE e
删除带有关系的节点
MATCH (cc: Profile1)-[Friends]->(c:Profile2)
DELETE cc,c,Friends
册除属性
- match (book{title:"book1 "})
- Remove book.price
- Return book
Delete与Remove
- DELETE操作用于删除节点和关联关系
- REMOVE操作用于删除标签和属性
删除标签:
- MATCH (m:Movie)
- REMOVE m:Picture
排序:
- MATCH (emp:Employee)
- RETURN emp.empid,emp.name,emp.salary,emp.deptno
- ORDER BY emp.name DESC
更高级的查询:
- MATCH (emp:Employee)
- WHERE emp.name = 'Abc'
- RETURN emp