📌前言:本篇博客介绍如何速通MySQL的第四篇,主要介绍Mysql中主要的基础的入门,学习MySQL之前要先安装好MySQL,如果还没有安装的小伙伴可以看看博主前面的博客,里面有详细的安装教程。或者看一下下面这个链接,以及第一篇还没看的也建议先看第一篇噢~
🚀如何安装Mysql
🚀【MySQL】如何速通MySQL(1)
🚀【MySQL】如何速通MySQL(2)
🚀【MySQL】如何速通MySQL(3)
在第三篇如何速通MySQL中我们学习了MySQL中的增删改查进阶和表的设计,有基础部分就有进阶部分嘛,接下来介绍的就是一些抽象的知识和如何和Java联系起来~话不多说,走起!
关于如何速通MySQL(3)中篇幅过长,没有介绍联合查询,想看联合查询的小伙伴可以转看这里噢~
【MySQL】MySQL表之联合查询(多表查询)
MySQL如何速通MySQL
- 一、索引
- 1. 索引介绍
- 2. 索引的使用
- 二、事务
- 1.ACID(数据库事务的四个基本特性)
- ① 原子性(Atomicity)
- ② 一致性(Consistency)
- ③ 持久性(Durability)
- ④ 隔离性(Isolation)
- 三、B+树
- 1.B树
- 2.B+树
- 3.B树和B+树之间的区别
- 四、JDBC编程
一、索引
1. 索引介绍
✅索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现,它可以提高查询效率、减少查询时间和减轻数据库负担。
对于数据库中的索引:
- 数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。
- 索引所起的作用类似书籍目录,可用于快速定位、检索数据。
- 索引对于提高数据库的性能有很大的帮助。
要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
- 数据量较大,且经常对这些列进行条件查询。
- 该数据库表的插入操作,及对这些列的修改操作频率较低。
- 索引会占用额外的磁盘空间。
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
2. 索引的使用
创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。
①.查看索引
show index from 表名
//show index from company;//查看公司表已有索引
查看索引的命令很简单,我们可以查看一下上面公司表的索引:
mysql> show index from company;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| company | 0 | PRIMARY | 1 | id | A | 7 | NULL | NULL | | BTREE | | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
上面的表中表示该表名为 company,索引类型为 B-Tree 索引,包含了一个主键索引(PRIMARY KEY),非唯一性索引(Non_unique = 0),索引名为 PRIMARY,索引的第一个列(Seq_in_index)为 id,使用的排序方式(Collation)为 A(升序排序),索引的基数(Cardinality)为 7等信息。
该索引的作用是加速对 company 表中 id 列的查询和排序操作。由于该表的主键索引是唯一性索引,因此查询时不会出现重复记录。
②.创建索引
对于非主键、非唯一约束、非外键的字段,可以创建普通索引
create index 索引名 on 表名(字段名);
//create index idx_company_name on company(name);
在company表中创建关于name的索引:
mysql> show index from company;
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| company | 0 | PRIMARY | 1 | id | A | 7 | NULL | NULL | | BTREE | | |
| company | 1 | idx_company_name | 1 | name | A | 7 | NULL | NULL | | BTREE | | |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
③.删除索引
drop index 索引名 on 表名;
//drop index idx_company_name on company(name);
二、事务
1.ACID(数据库事务的四个基本特性)
在 MySQL 中,事务是指一系列操作组成的逻辑单元,这些操作要么全部执行,要么全部撤销。
为什么要有事务呢,我们先用例子来了解一下:
有一天,小绿找小蓝借钱去约会,小蓝在转钱的时候但是数据库挂了,刚执行到减少小蓝2000余额的时候,后续操作即在小绿账户增加2000的数据库命令没有被执行…
这样子不就悲剧了?小蓝没了2000,小绿没了女神,我们得到了一个笑话,不不不,对于人道主义来说,还是要解决一下的!事务的本质就是将SQL命令打包,要么全部执行成功,要么全不执行。
解决方案:使用事务来控制,保证以上两句SQL要么全部执行成功,要么全部执行失败。
这就是数据库事务四个基本特性的其中一个,原子性,并不是说真的不执行,而是遇到执行到一半失败后,执行回滚操作,恢复到执行前的状态。既然讲到数据库事务四个基本特性,我们先来简单了解一下:
ACID是数据库事务的四个基本特性的首字母缩写,分别是:
- 原子性(Atomicity):指事务是一个不可分割的操作序列,要么全部执行成功,要么全部执行失败,不存在部分执行的情况。在执行过程中,如果出现故障或者错误,需要进行回滚操作,将数据库恢复到事务开始前的状态。
- 一致性(Consistency):指事务在执行前和执行后,数据库必须处于一致的状态。即事务执行前和执行后,数据库中的数据应该符合预设的规则和约束。
- 隔离性(Isolation):指并发执行的事务之间应该互相隔离,每个事务的执行都应该与其它事务的执行相互独立。换句话说,就是在同一时刻,对同一数据进行修改的事务应该互相隔离,避免干扰和冲突。
- 持久性(Durability):指一旦事务被提交,那么它所做的修改将会永久保存到数据库中,不会因为系统故障或者其他原因导致数据的丢失。
ACID是保证数据库事务正确执行和维护数据完整性的基础,这四个特性的组合能够确保在数据库的多个事务并发执行时,数据库的正确性和数据的一致性得到保障。同时,ACID也为数据库应用提供了可靠性和安全性,确保数据的正确性和稳定性。
① 原子性(Atomicity)
正如上面说的一样,过去的人们将原子认为是事物能够分割的最小单位,所以原子性就是,将这一系列操作看成是一个原子事件,要么全部执行成功,要么全部执行失败,不存在部分执行的情况。在执行过程中,如果出现故障或者错误,需要进行回滚操作,将数据库恢复到事务开始前的状态。
此处需要额外的部分来记录事务中的操作步骤,数据库里专门有个用来记录事务的日志,正因为如此,使用事务的时候,执行sql的开销会更大,效率会更低
在数据库使用时:
(1)开启事务: start transaction;
(2)执行多条SQL语句
(3)回滚或提交: rollback/commit;
说明: rollback即是全部失败,commit即是全部成功。
mysql> start transaction;//开启日志
mysql> insert into company(name, role, salary) values ('虾兵','小弟', 1599.20);//中间就是本事务要执行的每一步
mysql> insert into company(name, role, salary) values ('蟹将','小弟', 2000.99);//中间就是本事务要执行的每一步
mysql> commit;//提交事务,相当于事务执行完了
② 一致性(Consistency)
一致性(Consistency)指的是事务执行前后,数据库必须保持一致性状态。这里的一致性状态主要指的是数据的约束条件和完整性,例如主键、外键、唯一性约束、默认值、检查约束等。
具体来说,在 MySQL 中,可以通过以下方式来保证数据的一致性:
- 数据约束:创建表时,通过添加各种约束条件来限制数据的合法性,例如主键、唯一性约束、外键约束、默认值、检查约束等。
- 事务管理:对于需要进行多个操作的复杂业务逻辑,可以将这些操作放在一个事务中,使用 START TRANSACTION 和 COMMIT/ROLLBACK 等语句控制事务的提交和回滚。
- 锁机制:MySQL 提供了各种锁机制,例如共享锁、排他锁、行级锁、表级锁等,它们可以用来控制并发操作。
- 触发器:使用触发器可以在数据发生变化时自动触发一些操作,例如数据验证、数据更新等。
③ 持久性(Durability)
在 MySQL 中,持久性(Durability)是 ACID四种属性之一,指的是一旦一个事务被提交,其所做的修改就会永久保存到数据库中,即使系统崩溃也不会丢失数据。
实现持久性通常需要使用日志(Log)机制。在 MySQL 中,每个写操作都会被记录到 redo log(重做日志)中,只有当 redo log 中的所有操作都成功写入磁盘后,事务才被认为是持久性的。
当系统故障或者重启时,MySQL 会自动从 redo log 中恢复数据,确保数据不会丢失。同时,MySQL 也提供了多种备份和恢复机制,以确保数据的可靠性和可用性。
④ 隔离性(Isolation)
在 MySQL 中,隔离性(Isolation)是 ACID四种属性之一,指的是在多个并发事务同时修改数据库中的数据时,每个事务所看到的数据都必须与其期望的一致。隔离性的目的是为了保证各个并发事务之间的数据相互隔离,不会互相影响。
上面说到,ACID是保证多个事务并发执行的时候不会相互影响,实际上,并发性事务可能产生的问题主要有下面几个:
1.脏读问题
一个事务A正在对数据进行修改的过程中,还没提交之前,另外的事务B,也对同一个数据进行了读取,此时B的读操作就称为"脏读",读到的数据也称为"脏数据"。
解决方法:mysql引入写操作加锁,就是写操作和读操作不能并发,当写的时候禁止读,这样的加锁操作,降低并发程序(降低效率),提高隔离性(提高数据的准确性)
2.不可重复读
当事务1已经提交数据,此时事务2开始读数据,在读取过程中,事务3又提交了新的数据,此时意味着同一个事务2之内,多次读数据,读出来的结果是不一样的(预期是一个事务中,多次读取结果是一样的,就叫做不可重复读)
解决方法:mysql引入写操作加锁,就是读操作和写操作不能并发,当读的时候禁止写,同样是降低事务的并发能力,提高事务的隔离性
3.幻读
在读加锁和写加锁的前提下,一个事务两次读取同一个数据,发现读取的数据值是一样的,但是结果集不一样(如Student.java代码内容不变,但是第一次看到的只有Student.java这个文件,第二次看到的是Student.java和Teacher.java)
解决方法:数据库"串行化"这样的方式来解决幻读,彻底放弃并发处理事务,一个接一个的串行的处理事务。这样做并发程序是最低的(效率最慢的),隔离性也是最高的。
对应上述问题,mysql提供了4种隔离级别,就对应上面几个情况:
隔离级别 | 说明 |
---|---|
read uncommitted(读取未提交的数据) | 没有进行任何锁限制,并发最高(效率最高),隔离性最低(准确性最低) |
read committed(读取已提交的数据) | 给写加锁,并发程度降低,隔离性也提高了 |
repeatable read(可重复读) | 给写和读都加锁,并发性继续降低,隔离性又提高了 |
serializable(串行化) | 串行化,并发程度最低,隔离性最高 |
以上是MySQL内置的机制,可以通过修改mysql的配置文件,来设置当前mysql工作在哪种状态下,而上面的隔离级别如何选择,需要在实际需求中看业务场景,在准确性和效率之间衡量,比如转账的时候准确性要拉满,效率并不关键,而视频点赞等,要求快狠准,追求的是效率,准确性就不那么关键了。
三、B+树
B+树是一种为了数据结构索引、量身定做的数据结构。它是一种高效的索引结构,被广泛用于数据库和文件系统等应用中。
B+树是一种多路搜索树,区别于二叉搜索树,它允许每个节点存储多个关键字和数据信息。在B+树 中,所有数据都存储在叶子节点中,而非内部节点,而且所有叶子节点都有序排列形成一个链表,这使得 B+树可以支持范围查询和顺序遍历等操作。
要了解B+树,我们得先了解B树:
1.B树
B树是一种平衡多路搜索树,它能够在进行大量数据插入、删除、查找等操作时保持较好的平衡性能。
B树的节点有多个孩子,通常用一个数组来存放关键字和指向孩子节点的指针。B树的每个节点都有一个阶数,表示该节点最多包含的关键字数量。一棵m阶的B树有以下几个特点:
- 根节点至少有两个孩子,除根节点外,其它每个节点至少有m/2个孩子;
- 每个节点中的关键字按从小到大的顺序排列,位于关键字左右两侧的孩子节点中的关键字均大于左侧所有关键字,小于右侧所有关键字。
- 所有叶子节点都位于同一层,并不包含任何信息。
B树的平衡性能主要由它的节点阶数决定,节点阶数越大,B树高度越小,查找、插入和删除操作的效率越高。B树广泛应用于数据库系统中,如Oracle、MySQL等。
2.B+树
B+树的主要优点是支持高效的插入、查找、删除和遍历操作,可以快速定位到目标数据。同时,B+树还支持范围查询和排序等操作,因此被广泛应用于数据库和文件系统等领域。
B+树的特点:
①一个节点,可以存储N个key,N个key划分出了N个区间(而不是如B树的N+1个区间)
②每个节点中的key的值,都会在子节点中也存在(同时该key是子节点的最大值)
③B+树的叶子节点,是首位相连的,类似于一个链表
④由于叶子节点,是完整的数据集合,只在叶子节点这里存储数据表的每一行数据,而非叶子节点,只存key值本身即可
B+树的优势:
①.当前一个节点保存更多的key,最终树的高度是相对较矮的,查询的时候减少IO的访问次数(和B树一样,IO特指硬盘的访问)
②.所有的查询最终都会落在叶子节点上(查询任何一个数据,经过IO访问次数,是一样的),稳定,可以让程序员对于程序的执行效率有一个更准确的评估
③.B+树的所有叶子节点,构成链表,此时比较方便进行范围查询(如果查询5~11的数据,只需要先找5,再找11,沿着链表遍历即可)
3.B树和B+树之间的区别
B树和B+树是两种常见的平衡搜索树,它们有很多相似之处,但也有一些细节上的不同。
- 节点结构不同:B树的非叶子节点中既包含关键字,也包含数据指针,而B+树仅在叶子节点中存放数据指针,非叶子节点只存储关键字用于索引。这样做的优势在于B+树的叶子节点可以更多,从而减小了非叶子节点的数量,使得整棵树的高度更加均衡,查找时不会出现在非叶子节点中进行多次查找的情况,提高了查询效率。
- 叶子节点指针的数量不同:B树的叶子节点包含了实际存储的数据以及指向下一个兄弟叶子节点的指针,在B+树中,每个叶子节点都有一个指向下一个叶子节点的指针(双向链表),这样便于范围查找操作。
- 查找方式不同:在B树中,由于每个节点都存储了数据指针,因此在查找某个数据时,可能需要沿着非叶子节点找到叶子节点后再对比数据,而在B+树中,叶子节点就是存储数据的节点,查找时只需要迭代遍历叶子节点即可。
- 拆分方式不同:在B树中,当一个节点插入关键字后,如果节点中关键字的数量超过了阶数,则需要将该节点拆分为两个节点进行存储。而在B+树中,只有叶子节点需要拆分,非叶子节点只需要调整指针即可。
总之,B+树相对于B树来说,能够提高查询效率以及降低存储开销,并且适合在磁盘等外存介质上使用,因此在大规模数据存储和处理方面具有优越性。
最后,关于MySQL的表结构:MySQL组织数据的方式,我们看见一张"表"的时候,实际上这个表不一定是按照"表格"这样的数据,结构在硬盘上组织的,也有可能是按照这种树形结构组织。(具体是哪种结构,取决于表中有没有索引,以及数据库使用了哪种存储)
四、JDBC编程
在各种数据库中,MySQL,Oracle,SQL Server在开发的时候,就会提供一组编程接口(API)。基于一些功能去使用就可以了。对于数据库MySQL和Java之间,我们就用到了JDBC编程。
JDBC,即Java Database Connectivity
,java数据库连接。是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范。这个API由 java.sql.*,javax.sql.*
包中的一些类和接口组成,它为Java开发人员操作数据库提供了一个标准的API,可以为多种关系数据库提供统一访问。
通过DataSource(数据源)对象获取。实际应用中会使用DataSource对象:
DataSource ds = new MysqlDataSource();
((MysqlDataSource) ds).setUrl("jdbc:mysql://localhost:3306/test?");
((MysqlDataSource) ds).setUser("root");
((MysqlDataSource) ds).setPassword("root");
Connection connection = ds.getConnection();
这里不详细讲解JDBC的使用,只简单演示备份代码:
对于JDBC查询数据库数据代码:
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBC_Select {
public static void main(String[] args) throws SQLException {
//JDBC 需要通过以下步骤来完成开发
//1.创建并初始化一个数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java001?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("123456");
//2.建立连接
dataSource.getConnection();
Connection connection = dataSource.getConnection();
//3.构造SQL
String sql = "select * from student";
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行SQL语句
ResultSet resultSet = statement.executeQuery();
//5.遍历结果集合
while(resultSet.next()){
// 把 resultSet 想象成一个表格,同时表格这里有一个光标, 初始情况下光标指向表最上面
// 每次调用 next,光标往下走一行
// 当光标指向某一行的时候,就可以通过 getXXX 来获取到当前这行里的数据
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("id = "+ id + ", name = "+name);
}
//6.释放必要的资源
statement.close();
connection.close();
}
}
对于JDBC增加数据库数据代码:
public class JDBC_Insert {
public static void main(String[] args) throws SQLException {
//JDBC 需要通过以下步骤来完成开发
//1.创建并初始化一个数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java001?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("123456");
//2.和数据库服务器建立连接
dataSource.getConnection();
Connection connection = dataSource.getConnection();
//3.从控制台读取用户输入信息
Scanner scanner = new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name = scanner.next();
System.out.println("请输入学号:");
int id = scanner.nextInt();
//4.构造SQL语句
//String sql = "insert into student value(1, 'zs')";//插入的是写死的数据(硬代码)
//String sql = "insert into student value("+ id +", '"+ name +"')";有可能sql注入
String sql = "insert into student value(?, ?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1,id);
statement.setString(2,name);
//5.执行SQL语句
int ret = statement.executeUpdate();
System.out.println("ret = " + ret);
System.out.println(statement);
//6.释放必要的资源
statement.close();
connection.close();
}
}
这就是本篇如何速通MySQL全部内容啦,欢迎关注。一起学习,共同努力!
还有一件事: