MySQL&JDBC操作数据库&MySQL调优

注:本文章只讲述部分MySQL数据库和连接问题

MySQL概念&连接

  • MySQL概述
    • 开源免费的数据库,已经被Oracle收购,MySQL6.x版本开始就已经收费
  • MySQL的连接
    • 首先安装MySQL软件
    • 进行安装的时候设置连接密码,用户名默认是root
    • 进行远程连接(Navicat连接),本地的主机名就是localhost或者是127.0.0.1,如果是云服务器或者远程的服务器就是其主机号
      在这里插入图片描述

SQL语言

概述

数据库是不认识 JAVA 语言的,但是我们同样要与数据库交互,这时需要使用到数据库认识的语言: SQL 语句,它是数据库的代码。

SQL语法

  • a.SQL 语句可以单行或多行书写,每行可以加或者不加; 但是为了严谨性,我们一般在每行 SQL 语句末尾加上;
  • b.SQL 语句不区分大小写,建议用大写来书写 SQL 中关键字
  • c.注释:
    单行:1.#注释内容
    ​ 2.-- 注释内容
    ​ 多行的注释和Java的一样
  • 特殊的几个数据类型
    • decimal(指定小数最大长度,小数部分位数)
      例如:decimal(5,2):改小数最多 5 位,小数部分有两 位 312.00 333.55
    • date:为日期类型,只包含年月日
    • datetime:为日期类型,精确到秒
    • char和varchar区别:前者为固定字符串长度,后者是工具字符串长度来调整占用的字节长度

SQL分类

  1. 数据定义语言:简称 DDL(Data Definition Language),用来定义数据库对象:数据库,表, 列等。关键字:create,alter,drop 等
  2. 数据操作语言:简称 DML(Data Manipulation Language),用来对数据库中表的记录进行更新。 关键字:insert,delete,update 等
  3. 数据操作语言:简称 DML(Data Manipulation Language),用来对数据库中表的记录进行更新。 关键字:insert,delete,update 等
  4. 数据查询语言:简称 DQL(Data Query Language),用来查询数据库中表的记录。关键字:select, from,where 等

DDL语句操纵数据库

-- 1.查询所有数据库
SHOW DATABASES

-- 2.创建一个数据库test
CREATE DATABASE test

-- 3.查询数据库的定义信息
-- SHOW CREATE DATABASE 数据库名;
SHOW CREATE DATABASE test;

-- 4.切换或使用某个数据库
USE test

-- 5.删除数据库
DROP DATABASE test

DDL语句操纵数据库表

-- 创建一个数据库表student
CREATE TABLE student(
	-- 列名1 类型[约束],
    -- 列名2 类型[约束]......
);

-- 查看表定义信息
-- SHOW CREATE TABLE 表名;
SHOW CREATE TABLE student;

-- 删除数据库表
DROP TABLE student

-- 向数据库表中添加数据
INSERT INTO 表名 VALUES ('值 1','值 2',......)

多表查询

内连接查询

SELECT * FROM product p
INNER JOIN category c
ON p.cid = c.id;

外连接查询

-- 左外连接
SELECT * FROM product p LEFT OUTER JOIN category c
ON p.cid=c.id;

-- 右外连接
SELECT * FROM product p RIGHT OUTER JOIN category c
ON p.cid=c.id;

JDBC操作MySQL

JDBC概述

  • JDBC(Java Data Base Connectivity,java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以 为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。是 Java 访问数据库的 标准规范
  • 实现原理图
    在这里插入图片描述
  • JDBC 是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!
  • 每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库厂商提供
  • SQL注入
    • 在JDBC注册完成后,进行测试
      利用拼接的方式,会有SQL注入的漏洞
      我们就要利用PreparedStatement 预编译 SQL,利用问号占位符的方式来防止SQL注入漏洞

连接池技术

  • 用池来管理 Connection,这样可以重复使用 Connection。有了池,所以我们就不用自己来创建 Connection,而是通过池来获取 Connection 对象。当使用完 Connection 后,调用 Connection 的 close() 方法也不会真的关闭 Connection,而是把 Connection“归还”给池。池就可以再利用这个 Connection 对象了。
  • Java 为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实 现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

DBCP连接池

DBCP 是一个开源的连接池,是 Apache Common 成员之一,在企业开发中也比较常见,tomcat 内 置的连接池。

DBCP基本使用

/**
* 使用 DBCP 连接池
*/
public class DBCPDemo {
 @Test
 public void test() throws Exception {
 //1.使用 BasicDataSource 基础数据源
 BasicDataSource bs = new BasicDataSource();
 //2.设置数据库连接参数
 bs.setDriverClassName("com.mysql.jdbc.Driver");

bs.setUrl("jdbc:mysql://192.168.1.231:3306/test02?useSSL=false&characterEncodi
ng=UTF-8");
 bs.setUsername("root");
 bs.setPassword("123456");
 //3.从数据源中获取一个连接
 Connection con = bs.getConnection();
 System.out.println(con);
 }
}

事务管理

事务概述

事务是指逻辑上的一组操作(对于数据库来说,就是多条 SQL语句),这一组操作中包含单个操作要么 全部成功,要么全部失败

MySQL管理事务

-- MySQL 中事务默认是自动提交(数据永久改变),每执行一条 SQL,就会提交一个事务
 UPDATE account SET money=money-1000 WHERE name='zhangsan';
 SELECT * FROM account;
#a.通过 SQL 语句开启事务
 -- 开启一个事务
 START TRANSACTION;
 UPDATE account SET money=money-1000 WHERE name='zhangsan';
 SELECT * FROM account;
 -- 假设转账失败,此时我们可以还原 zhangsan 的余额
 ROLLBACK;
 SELECT * FROM account;
#b.关闭自动提交
 -- 查看 MySQL 自动提交变量
 SHOW VARIABLES LIKE '%commit%';
 -- 关闭自动提交,一旦关闭自动提交,相当于在执行每条 SQL 语句前,执行一次 START TRANSACTION;
 SET AUTOCOMMIT=OFF;
 
 UPDATE account SET money=money-1000 WHERE name='zhangsan';
 SELECT * FROM account;
 -- 假设转账失败,此时我们可以还原 zhangsan 的余额
 ROLLBACK;
 SELECT * FROM account;
  • JDBC事务管理利用rollback来进行数据的回滚来实现

  • DBUtils事务管理利用DbUtils.rollbackAndCloseQuietly(conn)来实现

事务管理四大特性(ACID)

1.原子性:事务中的操作是不可分割的,要么都成功,要么都失败

2.一致性:保证数据完整性,例如:删除种类表 id=3 的种类,但是我们没有删除商品表中 cid=3 对应 的商品信息
​ 此时商品表中依赖 cid=3 种类信息丢失,破坏数据一致性
​ 我们需要先删除商品表中 cid=3 的所有商品信息,然后在删除种类表中 id=3 的种类信息

3.隔离性:多个事务操作一条数据记录,事务之间应该相互隔离,不受影响

4.持久性:事务一旦提交(commit),数据将将永久改变,不能恢复

可能产生的安全性问题

多个事务操作数据库同一份数据,如果不考虑隔离性会引发一些安全性问题:
1.脏读: 一个事务读到了另一个事务未提交的数据
2.不可重复读: 一个事务读到了另一个事务已经提交的 update 语句的数据,导致一个事务中出 现多次查询,查询结果结果不一致
3.虚读: 一个事务读到了另一个事务已经提交的 insert 语句的数据,导致一个事务中出现多次 查询,查询结果结果不一致

需要使用数据库隔离级别来解决上面三种问题:
1.read uncommitted : 未提交读 脏读,不可重复读,虚读都有可能发生
2.read committed : 已提交读 避免脏读, 不可重复读和虚读都有可能发生
3.repeatable read: 可重复读 避免脏读和不可重复读,虚读有可能发生
4.serializable: 串行化 避免脏读,不可重复读,虚读 会导致一个事务未执行完,其它事务无法执行

从上到下,安全性依次递增,效率依次递减 MySQL 数据库默认隔离级别:repeatable read

SQL索引

语法结构

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
ON table_name (column_name1 [ASC|DESC], column_name2 [ASC|DESC],...);

--  UNIQUE :创建唯一索引,确保索引列中的值是唯一的。
--  FULLTEXT :创建全文索引,用于对文本类型的列进行全文搜索。
--  SPATIAL :创建空间索引,用于对空间数据类型的列进行空间操作。
--  index_name :索引的名称。
--  table_name :要创建索引的表名。
--  column_name1 、 column_name2 等:要创建索引的列名,可以是单个列或多个列。
--  ASC 或 DESC :指定索引列的排序顺序,默认为升序(ASC)。

示例

  1. 创建单个列的普通索引:
CREATE INDEX idx_customername
ON customers (customer_name);

这将在 customers 表的 customer_name 列上创建一个名为 idx_customername 的普通索引。

2.创建多个列的复合索引:

CREATE INDEX idx_orderdetails
ON order_details (product_id, quantity);

在 order_details 表的 product_id 和 quantity 列上创建一个名为 idx_orderdetails 的复合索引。

  1. 创建唯一索引:
CREATE UNIQUE INDEX idx_useremail
ON users (user_email);

在 users 表的 user_email 列上创建一个唯一索引,确保该列中的值是唯一的。

:不同的数据库系统提供了不同的方式来重建索引,例如在 MySQL 中可以使用 ALTER TABLE… ENGINE=InnoDB 语句来重建表和索引。

SQL优化的方法

一、查询语句(SELECT)优化

  1. 避免使用 SELECT *,只选择需要的列,减少数据传输量和查询开销。
  • 例如: SELECT column1, column2 FROM table_nameSELECT * FROM table_name 更高效。
  1. 添加合适的索引:索引可以大大提高查询速度。
  • 根据查询条件和表的结构,选择合适的列创建索引。
  • 例如,如果经常根据某个字段进行查询,可以在该字段上创建索引。
  1. 避免在索引列上进行函数操作:这会导致索引无法使用。
  • 错误示例:
 SELECT * FROM table_name WHERE UPPER(column_name) = 'SOME_VALUE' 

正确做法是在应用程序中处理函数操作,或者在数据库设计时考虑使用合适的数据类型避免函数操作。
4. 限制返回行数:使用 LIMIT 语句限制返回的行数,特别是在处理大量数据时。

  • 例如: SELECT * FROM table_name LIMIT 100

二、连接查询优化

  1. 确保连接条件正确且高效:连接条件应该基于有索引的列,并且连接类型(内连接、左连接、右连接等)应该根据实际需求选择。
  • 例如,在两个大表连接时,确保连接条件的列上有索引可以提高连接效率。
  1. 避免笛卡尔积:在多表连接时,确保有正确的连接条件,避免产生笛卡尔积,这会导致查询性能急剧下降。
  • 检查连接语句中的 ON 子句,确保连接条件准确无误。

三、存储过程和函数优化

  1. 减少存储过程和函数的复杂性:过于复杂的存储过程和函数可能会导致性能问题。尽量将复杂的逻辑拆分成多个简单的步骤。

    • 例如,如果一个存储过程中有大量的嵌套循环和复杂的计算,可以考虑将一些计算逻辑提取到单独的函数中,以便更好地维护和优化。
  2. 避免在存储过程和函数中进行大量的数据操作:如果可能,尽量在存储过程和函数之外进行数据的批量处理,然后将处理后的结果传递给存储过程或函数进行进一步的操作。

    • 例如,不要在存储过程中进行大量的插入、更新或删除操作,而是在外部程序中准备好数据,然后通过参数传递给存储过程进行少量的操作。

四、数据库设计优化

  1. 规范化数据库设计:合理的数据库设计可以减少数据冗余,提高数据的一致性和查询性能。

    • 遵循数据库规范化原则,将数据拆分成多个表,并通过外键关联起来。
    • 例如,将客户信息和订单信息分别存储在两个表中,通过客户 ID 进行关联。
  2. 避免过度规范化:过度规范化可能会导致过多的连接操作,影响查询性能。在某些情况下,可以适当的反规范化,以提高查询速度。

    • 例如,将一些经常一起查询的字段冗余存储在一个表中,避免频繁的连接操作。

五、其他优化方法

监控数据库性能:使用数据库监控工具,实时监测数据库的性能指标,如查询响应时间、CPU 使用率、内存使用率等。

  • 根据监控结果,及时发现性能问题并进行优化。

MySQL调优

一、监控报警

监控工具(例如有:Prometheus+Grafana)监控MySQL,如果发现查询性能变慢,报价提醒运维人员来进行排查

二、排查慢SQL

  • 查看慢查询次数:
show status like 'slow_queries';
  • 开启慢查询日志,修改慢查询阈值:
set slow_query_log='ON';  -- 开启慢查询日志
set long_query_time = 1;  -- 设置慢查询阈值
  • 找出最慢的几条SQL
    • 慢查询日志分析工具mysqldumpslow找到最慢的几条语句
    • 示例,按照查询时间排序,查看前五条慢查询SQL语句

mysqldumpslow 命令的具体参数如下:

  • -a: 不将数字抽象成N,字符串抽象成S
  • -s: 是表示按照何种方式排序
  • c: 访问次数
  • l: 锁定时间
  • r: 返回记录
  • t: 查询时间
  • al:平均锁定时间
  • ar:平均返回记录数
  • at:平均查询时间 (默认方式)
  • ac:平均查询次数
  • -t: 即为返回前面多少条的数据;
  • -g: 后边搭配一个正则匹配模式,大小写不敏感的;
mysqldumpslow -s t -t 5 /var/lib/mysql/xxx-slow.log
  • 分析查询计划
    explan分析sql执行计划

三、MySQL调优

1.基础优化
  • 缓存优化
    mysql调整缓冲池大小等参数,引入redis
  • 硬件优化
    服务器加内存条、升级SSD固态硬盘、把磁盘I/O分散在多个设备、配置多处理器
  • 参数优化
  • 使用合适的存储引擎
    MyISAM:适合读取频繁,写入较少的场景(因为表级锁、B+树叶存储地址)
    InnoDB:适合并发写入场景(因为行级锁、B+树叶存记录)
  • 读写分离
  • 分库分表
    垂直拆分(分库)、水平拆分(分表)、垂直+水平拆分(分库分表)
2.表设计优化
  • 混合业务分表、冷热数据分表
  • 联合查询改为中间关系表
  • 遵循三个范式
    每个属性不可再分、表必须有且只有一个主键、非主键列必须直接依赖主键
  • 字段建议非空约束
    null值会有很多问题
  • 数据类型优化
    能整数就不要文本类型
    避免使用TEXT、BLOB数据类
    避免使用枚举类型,因为排序很慢
    使用TIMESTAMP存储时间,因为使用的是4字节,DATETIME使用8字节,缺点是只能存到2038年,MySQL5.6.4版本可以参数配置,自动修改为BIGINT类型
    DECIMAL存浮点数
3.索引优化
  • 考虑索引失效的11个场景
  • 遵循索引设计原则
  • 连接查询优化
  • 子查询优化
  • 分组优化
  • 深度分页查询优化
4.SQL优化

就在上一个目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值