11、数据库性能测试
MySQL事务
什么是事务?
数据库事务通常指对数据库进行读或写的一个操作过程
事务的两个目的:
- 为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法
- 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰
事务的特性(ACID)
- 原子性(Atomicity):事务必须是原子工作单元,一个事务中的所有语句,应该做到:要么全做,要么一个都不做。
- 一致性(Consistency):让数据保持逻辑上的“合理性”,比如:小王给小张打10000块钱,既要让小王的账户减少 10000,又要让小张的账户上增加10000块钱。
- 隔离性(Isolation):如果多个事务同时并发执行,但每个事务就像各自独立执行一样。
- 持久性(Durability):一个事务执行成功,则对数据来说应该是一个明确的硬盘数据更改(而不仅仅是内存中的变化)。
注意:如果要使用事务,表的引擎要为innodb引擎
事务的实现
- 事务的开启:begin; 或者start transaction
- 事务的提交:commit;
- 事务的回滚:rollback
开启autocommit(临时生效)
OFF(0):表示关闭
ON (1):表示开启
开启autocommit(永久生效)
修改配置文件:my.cnf 在[mysqld]下面加上:autocommit=1 重启服务才会生效
事务的实例
创建一个账户表模拟转账
MySQL视图
视图
什么是视图?
- 视图(view)是一种虚拟存在的表,是一个逻辑表,它本身是不包含数据的。作为一个select语句保存在数据字典中的。 通过视图,可以展现基表(用来创建视图的表叫做基表base table)的部分数据,也就是说视图的数据就是来自于基表
创建的基本语法是:
- create view <视图名称> as select 语句;
- create view <视图名称> (字段) as select 语句;
- create or replace view <视图名称> ;
修改的语法是:
- alter view <视图名称> as select 语句;
视图删除语法:
- drop view <视图名称> ;
视图的优点
- 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
- 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现
- 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。
- 不占用空间:视图是逻辑上的表,不占用内存空间。
总之,使用视图的大部分情况是为了保障数据安全性,提高查询效率
视图的缺点
- 性能差:必须把视图查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,数据库也要把它变成一个复杂的结合体,需要花费一定的时间。
- 修改限制:当用户试图修改视图的某些信息时,数据库必须把它转化为对基本表的某些信息的修改,对于简单的视图来说,这是很方便的,但是,对于比较复杂的视图,可能是不可修改的
MySQL触发器
触发器就是监视某种情况,并触发某种操作
创建触发器的语法
- after/before:可以设置为事件发生前或后
- insert/update/delete:它们可以在执行insert、update或delete的过程中触发
- for each row:每隔一行执行一次动作
删除触发器的语法
触发器实例-1
触发器实例-2
delimiter // 自定义语句的结束
new:指的是事件发生before或者after保存的新数据
MySQL存储过程
什么是存储过程?
- 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数来调用执行
优点:
- 复杂操作,调用简单
- 速度快
缺点:
- 封装复杂
- 没有灵活性,存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同,当切换到其他厂商的数据库系统时,需要重写原有的存储过程
存储过程
参数:
- in|out|inout 参数名称 类型(长度)
- in:表示调用者向过程传入值(传入值可以是字面量或变量)
- out:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
- inout:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
- 声明变量:declare 变量名 类型(长度) default 默认值;
- 给变量赋值:set @变量名=值;
- 调用存储命令:call 名称(@变量名);
- 删除存储过程命令:drop procedure 名称;
- 查看创建的存储过程命令:show create procedure 名称;
存储引擎
什么是数据库存储引擎?
- 数据库引擎是数据库底层软件组件,不同的存储引擎提供不同的存储机制,索引技巧,锁定水平等功能,使用不同的数据库引擎,可以获得特定的功能
我的理解:汽车引擎,有的适合爬坡,有的适合高速。存储引擎,处理不同的业务场景,不同的数据,产生不同的效果
索引中会体现,不同的引擎有不同的效果
查看存储引擎
- 如何查看数据库支持的引擎 show engines;
- 查看当前数据的引擎: show create table 表名;
- 查看当前库所有表的引擎: show table status;
建表时指定引擎
修改表的引擎
MyISAM与InnoDB的区别
如何选择引擎
- 是否要支持事务,如果要请选择InnoDB,如果不需要可以考虑MyISAM
- 有很多count计算,建议MyISAM
- 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读也有写,请使用InnoDB。
- 可靠性要求高的,或者要求支持事务,请使用InnoDB。
- 想要用到外键约束的时候,请使用InnoDB
- 如果不知道用什么,那就用InnoDB
索引
什么是索引
- 索引是一个单独的,存储在磁盘中上的数据库结构,它们包含着对数据表里的所有记录的引用指针。使用索引可以快速的找出在某列或多列中有特定值的行
索引特点
索引的优点
- 通过创建唯一索引,来保证数据库表中的每一行数据的唯一性
- 可以加快数据的检索速度
- 可以保证表数据的完整性与准确性
索引的缺点
- 索引需要占用物理空间
- 对表中的数据进行改动时,索引也需要跟着动态维护,降低了数据的维护速度
索引的常见类型
- index:普通索引
- unique:唯一索引
- primary key:主键索引
- foreign key:外键索引
- fulltext: 全文索引
- 组合索引
数据准备
public static String getRandomString(int length){
String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random=new Random();
StringBuffer sb=new StringBuffer();
for(int i=0;i<length;i++){
int number=random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
String driverStr="com.mysql.jdbc.Driver";
String connStr="jdbc:mysql://localhost:3306/test?useSSL=false";// 所有异常抛出
Class.forName(driverStr) ;// 加载驱动程序
Connection conn = null ;
conn = DriverManager.getConnection(connStr,"root","123456") ;
// 数据库连接
PreparedStatement pstmt = null ;// 数据库操作
for(int i=0;i<1000000;i++) {
String sql = "INSERT INTO test_index(username,password,createtime) VALUES (?,?,?) " ;
pstmt = conn.prepareStatement(sql) ;
pstmt.setString(1,"user_"+i) ;
pstmt.setString(2,getRandomString(7)) ;
pstmt.setTimestamp(3,new Timestamp(( new java.util.Date()).getTime()));
int t = pstmt.executeUpdate() ;// 执行更新
}
pstmt.close() ;
conn.close() ;// 数据库关闭
普通索引与唯一索引
- 普通索引(index):各类索引中最为普通的索引,主要任务就是提高查询速度。其特点是允许出现相同的索引内容,允许空(null)值。
- 唯一索引(unique):不可以出现相同的索引内容,但是允许空(null)值
创建表的时候创建
create table test (
id int(7) zerofill auto_increment not null,
username varchar(20),
servnumber varchar(30),
password varchar(20),
createtime datetime,
unique (id)
)DEFAULT CHARSET=utf8;
直接为表添加索引
语法: alter table 表名 add index 索引名称 (字段名称);
eg: alter table test add unique unique_username (username);
直接创建索引
语法:create index 索引 on 表名 (字段名);
eg:create index index_createtime on test (createtime);
create unique index index_createtime on test (createtime);
主键索引
把主键添加索引就是主键索引,它是一种特殊的唯一索引,不允许有空值,而唯一索引(unique是允许为空值的)。指定 为“PRIMARY KEY”
主键:主键是表的某一列,这一列的值是用来标志表中的每一行数据的。
注意:每一张表只能拥有一个主键
解释主键,就是某一列,用来关联其他表的外键,每一张表只能有一个主键。表示唯一一条数据
全文索引
全文索引是将存储在数据库中的文章或者句子等任意内容信息查找出来的索引,单位是词。全文索引也是目前搜索引擎使用的一种关键技术。指定为 fulltext
注意
- 一般情况下创建全文索引的字段数据类型为 char、varchar、text 。其它字段类型不可以
- 全文索引不针对非常频繁的词做索引。比如is,no,not,you,me,yes这些,我们称之为停止词
- 对英文检索时忽略大小写
使用全文索引
语法:select * from 表名 where match (字段名) against ('检索内容’);
eg:select * from command where match(instruction) against ('sections’);
查看匹配度:
select id, match (字段名) against ('检索内容’) from command;
停止词:
出现频率很高的词,将会使全文索引失效,比如is,no,not,you,me,yes
in boolean mode模式
使用通配符*时,只能放在词的后边,不能放前边
select * from command where match(instruction) against ('director*' in boolean mode);
外键索引
外键就是作用于两个表数据之间的链接的一列或多列,用来保证表与表之间的数据的完整性和准确性
注意
- 主键跟外键的字段类型一定要相同
- 要使用外键约束表的引擎一定得是MyISAM引擎,InnoDB是无法创建的
- 在干掉外键索引之前必须先把外键约束删除,才能删除索引
联合索引
又称组合索引或者复合索引,是建立在俩列或者多列以上的索引。联合索引的最左原则
总结
- 索引并非越多越好,过多的索引会增加数据的维护速度,造成磁盘空间的浪费
- 当表的数据量很大的时候,可以考虑建立索引
- 表中经常查数据的字段,可以考虑建立索引
- 想要保证表中数据的唯一性,可以考虑建立唯一索引
- 想要保证两张表中的数据的完整性跟准确性,可以考虑建立外键约束
- 经常对多列数据进行查询时,可以考虑建立联合索引
- 单表中索引数量不超过5个
数据库慢查询与优化
MySQL慢查询
- 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。
- 注意:不同系统定义不同的慢查询指标
编辑/etc/my.cnf,在[mysqld]域中添加:
- slow_query_log = ON
- slow_query_log_file = /usr/local/mysql/data/slow.log
- long_query_time = 1
MySQL慢查询
- 查看是否已经开启了慢查询日志 show variables like 'slow%’;
- 开启慢查询日志 set global slow_query_log = on ;
- 查看慢查询的时间临界值 show variables like '%long%’;
- 设置慢查询的时间标准 set long_query_time=0.4;
未使用索引的查询也被记录到慢查询日志中 log_queries_not_using_indexes=1
sql语句执行过程解析
- 查看性能详情是否开启 show variables like '%profiling%’;
- 开启性能记录功能 set profiling = on ;
- 查看性能的记录 show profiles;
- 查看语句的执行性能详情 show profile for query 4;
SQL语句性能分析
使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的。分析查询语句或是表结构的性能瓶颈。
用法:explain select 语句
explain select * from test_index_demo where id=98765;
SQL语句性能调优
- 尽量避免使用select *from ,尽量精确到想要的结果字段
- 尽量避免条件使用or,使用in
- 记得加上limit 限制行数,避免数据量过大消耗性能
- 使用模糊查询时,%放在前面是会使索引失效
- 要小心条件字段类型的转换(varchar类型查询应该加引号)