当前位置: 首页 > news >正文

mysql——索引事务和JDBC编程

1. 索引

索引是数据库中用于加速查询的数据结构,类似于书籍的目录。

索引的作用

  • 大幅提高查询速度

  • 加速表连接操作

  • 保证数据唯一性(唯一索引)

  • 优化排序和分组操作

创建主键约束( PRIMARY KEY )、唯一约束( UNIQUE )、外键约束( FOREIGN KEY )时,会自动创建对应列的索引。

1. 创建索引

对于非主键、非唯一约束、非外键的字段,可以创建普通索引
create index 索引名 on 表名(字段名);
2. 查看索引
show index from 表名;

3. 删除索引

drop index 索引名 on 表名;
对于 创建主键约束( PRIMARY KEY )、唯一约束( UNIQUE )、外键约束( FOREIGN KEY )时,自动创建对应列的索引,是无法手动删除的
自定义索引可以手动删除。

1. 按数据结构分类

如果索引不存在,当我们想要查找某个数据时,时间复杂度为O(N)

1. 哈希索引
  • 特点

    • 基于哈希表实现

    • 精确匹配效率极高(O(1)时间复杂度)

    • 不支持范围查询和排序

  • 适用场景:等值查询(=, IN)

  • 存储引擎支持:MEMORY引擎(默认)、InnoDB(自适应哈希索引)

2. 二叉搜索树
有可能为单分支二叉搜索树则时间复杂度为O(N)
3. 红黑树
可以避免成为单分支二叉搜索树,时间复杂度为O(logN)
4. B 树(N叉搜索树)
  • 特点:默认索引类型,多路平衡查找树

每个节点上有 M 个key ,划分出了 M+1 个区间

进行查询时,直接从根节点出发,判断当前要查的节点在哪个区间中,决定下一步往哪里走

进行 插入/删除操作时可能涉及到节点的拆分和合并

  • 适用场景

    • 全值匹配(=)

    • 范围查询(>, <, BETWEEN)

    • 前缀匹配(LIKE 'abc%')

    • 排序(ORDER BY)

    • 分组(GROUP BY)

无法使用后缀匹配(like '%abc')

  • 存储引擎支持:InnoDB、MyISAM、MEMORY等

5. B+树
B 树的改进,针对数据库量身定做
特点:
1. B+ 树也是一个N叉搜索树,每个节点上有 M 个key ,划分出了 M 个区间
2. 父节点上的每个key都会以最大值的身份存储在子节点中,所以叶子节点这一层包含了整个树的数据全集
3. B+ 树会使用链表将叶子节点串联起来
(此时就可以非常方便的完成数据集合的遍历,也可以很方便的从数据集合中按照范围取出一个子集)
优点:
1. N 叉搜索树,树的高度是有限的,降低 io 的次数
2. 擅长范围查询
3. 所有查询最终都要落到叶子节点,查询和查询之间的时间开销是稳定的
4. 由于叶子节点是全集,会把行数据只存储在叶子节点上,非叶子节点只存储一个用来排序的key
5. 在进行查询时,可以将硬盘中的非叶子节点加载到内存中,整体查询的比较过程就可以在内存中进行。

2. 事务

A给B转2000块钱,在转账过程中,A的账户扣除2000块钱,此时突然断网或数据库挂了,B的账号没有增加2000块钱,这是一个重大错误。

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。
使用:
1 )开启事务: start transaction;
2 )执行多条 SQL 语句
3 )回滚或提交: rollback/commit;
说明: rollback 即是全部失败, commit 即是全部成功。
事务特性:
1. 原子性:通过回滚的方式,保证这一系列操作都能执行正确或恢复如初

2. 一致性:事务执行前后,数据库从一个一致状态变到另一个一致状态

  • 数据完整性约束不被破坏

  • 业务规则保持一致

3. 持久性:事务一旦提交,其结果就是永久性的 :即使系统崩溃,数据也不会丢失
通过redo log(重做日志)实现
4.  隔离性:多个事务 并发执行时,一个事务的执行不应影响其他事务
通过锁机制和MVCC(多版本并发控制)实现
提高并发进程,数据库服务器执行效率变高,但会产生问题

数据隔离级别

隔离级别脏读不可重复读幻读说明
READ UNCOMMITTED可能可能可能可读取未提交数据
READ COMMITTED不可能可能可能只能读取已提交数据(读加锁)
REPEATABLE READ不可能不可能可能

同一事务多次读取结果一致(MySQL默认)

(读写都加锁)

SERIALIZABLE不可能不可能不可能完全串行化执行

1. 查看和设置隔离级别

-- 查看当前隔离级别
SELECT @@transaction_isolation;-- 设置会话级隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;-- 设置全局级隔离级别(需重启生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

2. 隔离级别问题演示

  • 锁机制

    • 共享锁(S锁):读锁,其他事务可读不可写

    • 排他锁(X锁):写锁,其他事务不可读写

(1) 脏读(Dirty Read)

一个事务A 在写数据的过程中,事务B读取了该数据,之后事务A又修改了该数据,导致事务B之前读取的数据时一个无效/过时的数据(也称为 脏数据)

-- 会话1
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;  -- 未提交-- 会话2(可以读取到未提交的数据)
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT balance FROM accounts WHERE user_id = 1;  -- 看到未提交的修改

解决方法:

在事务A进行写操作时加锁(即在事务A进行写操作时,事务B不可以进行读操作)

(2) 不可重复读(Non-repeatable Read)

事务A提交一份数据后,事务B进行多次读取,在事务B读取数据过程中,事务A又修改了该数据并提交,导致事务B读取的前后数据不同。

-- 会话1
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT balance FROM accounts WHERE user_id = 1;  -- 第一次读取-- 会话2
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
COMMIT;-- 会话1(同一事务内两次读取结果不同)
SELECT balance FROM accounts WHERE user_id = 1;  -- 第二次读取
COMMIT;

解决方法:

在事务B进行读操作时加锁(即在事务B读操作时,事务B不可以进行写操作)

在事务A进行写操作时加锁(即在事务A进行写操作时,事务B不可以进行读操作)

(3) 幻读(Phantom Read)

事务A提交一份数据后,事务B进行多次读取,在事务B读取数据过程中,事务A又提交了一份数据,导致事务B读取的前后结果集不同。

-- 会话1
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM accounts WHERE balance > 1000;  -- 返回2条记录-- 会话2
INSERT INTO accounts VALUES(3, '王五', 1500);
COMMIT;-- 会话1(同一事务内相同查询返回不同行数)
SELECT * FROM accounts WHERE balance > 1000;  -- 返回3条记录
COMMIT;

解决方法:

引入串行化方式

总结:

1 )对于插入、删除数据频率高的表,不适用索引
2 )对于某列修改频率高的,该列不适用索引
3 )通过某列或某几列的条件查询频率高的,可以对这些列创建索引

3. JDBC 编程

编程语言,如 Java C C++ Python
数据库,如 Oracle MySQL SQL Server
数据库驱动包:不同的数据库,对应不同的编程语言提供了不同的数据库驱动包,如: MySQL
供了 Java 的驱动包 mysql-connector-java ,需要基于 Java 操作 MySQL 即需要该驱动包。同样的,
要基于 Java 操作 Oracle 数据库则需要 Oracle 的数据库驱动包 ojdbc
JDBC ,即 Java Database Connectivity java 数据库连接。是一种用于执行 SQL 语句的 Java API ,它是Java中的数据库连接规范。这个 API java.sql.*,javax.sql.* 包中的一些类和接口组成,它为 Java 开发人员操作数据库提供了一个标准的API ,可以为多种关系数据库提供统一访问。

配置:

1. 从中央仓库下载mysql的jdbc驱动包(jar)

2. 将 jar 引入到项目中(拷贝,add as library)

高内聚:把相同/相关联的功能放在一起

高耦合:两个模块关联关系紧密,一个模块修改对另一个模块有很大影响

我们要求程序 高内聚,低耦合

jdbc开发案例

javax.sql jdbc 包

127.0.0.1 是一个特殊的IP地址,叫做“环回IP”(lookback)

每个机器上都有环回IP(127.0.0.1),只要把消息发送给这个IP,就等于发给自己

由于我们的jdbc程序和mysql服务器在同一个主机上,使用环回IP

import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class Domo {public static void main(String[] args) throws SQLException {Scanner scan = new Scanner(System.in);System.out.print("请输入id:");int id = scan.nextInt();scan.nextLine();System.out.print("请输入姓名:");String name = scan.nextLine();//1.创建DataSource(抽象接口)//DataSource 描述“数据源头”,即数据库服务器所在位置DataSource dataSource = new MysqlDataSource();//找到mysql服务器//url(网址):网络上具体资源位置((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/school?characterEncoding=utf8&useSSL=false");//向下转型//认证用户名//root 管理员mysql默认自带用户((MysqlDataSource) dataSource).setUser("root");//认证密码((MysqlDataSource) dataSource).setPassword("123");//2. 和数据库服务器建立连接//getConnection()是jdbc中常见异常,如果执行sql或操作数据库过程中出现问题,一般都抛出这个异常//connection连接Connection connection=dataSource.getConnection();//3. 构造sql(代码中的sql不需要写;)String sql = "insert into student values(1,'lh'),(id,'"+ name +"'),(?,?)";PreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,id);preparedStatement.setString(2,name);//4. 把sql发送给服务器,返回值是一个整数,表示影响的行数int n = preparedStatement.executeUpdate();System.out.println(n);//5. 释放资源,关闭连接(先申请资源,后释放)preparedStatement.close();connection.close();}
}

Prepared :准备好的/预处理的

Statement: 语句

先解析检查 sql ,看看sql是否有问题,解析完毕后,会得到结构化数据,直接把解析好的结构化数据发送给数据库,服务器就省下了这部分解析工作

如果直接把字符串格式的 sql 发给mysql 服务器,mysql 服务器就需要对 sql 解析和校验,但 mysql 服务器是服务于多个客户端,此时总的开销和总的负担就很大。

import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Domo2 {public static void main(String[] args) throws SQLException {//建立DataSouece(抽象接口)DataSource dataSource = new MysqlDataSource();((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/school?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("123");//2. 和数据库服务器建立连接Connection connection = dataSource.getConnection();//3. 构造sqlString sql = "select * from student";PreparedStatement statement = connection.prepareStatement(sql);//4. 执行sql//ResultSet 表示查询的结果集合ResultSet resultSet = statement.executeQuery();//5. 遍历结果集合while(resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");System.out.println("id = "+id +", name ="+ name);}//释放资源resultSet.close();statement.close();connection.close();}
}

相关文章:

  • 项目——高并发内存池
  • RHCE练习1
  • C语言——函数
  • Spring Security认证流程
  • nacos配置springboot配置信息,并且集成金仓数据库
  • 精选面试题
  • 【解决】Android Gradle Sync 报错 Could not read workspace metadata
  • 程序员鱼皮最新项目-----AI超级智能体教程(一)
  • 04-stm32的标准外设库
  • 【C语言】C语言动态内存管理
  • MS1205N激光测距用高精度时间测量(TDC)电路,单精度模式 60ps,双精度模式 30ps
  • LJF-Framework 第15章 想想搞点啥-若依管理系统兼容一下
  • 机器学习项目管理:团队协作与版本控制
  • aarcpy 列表函数的使用(1)
  • MCP‌和LangGraph‌结合2
  • 第十节:性能优化高频题-虚拟DOM与Diff算法优化
  • 探寻健康密码:养生从日常细节开始
  • ap无法上线问题定位(交换机发包没有剥掉pvid tag)
  • 机械手排列定位设备 PLC梯形图流程
  • 通信新思路:EtherCAT转Profinet网关在自主研发机器人中的技术实践与优化
  • 迎接神十九乘组回家,东风着陆场各项工作已准备就绪
  • 五一假期上海路网哪里易拥堵?怎么错峰更靠谱?研判报告来了
  • 当哲学与戏剧作为一种生活方式——《人生六戏》分享会
  • 新华视点丨广西抗旱一线调查
  • 长三角议事厅|国际产业转移对中国产业链韧性的影响与对策
  • 河南省鹤壁市人大常委会副主任李杰接受审查调查