Ykuri98
文章46
标签14
分类1
学习总结(2022.05.17-2022.05.23)

学习总结(2022.05.17-2022.05.23)

索引

索引是一种帮助提高查询速度的数据结构,可以提高MySQL的查询语句的效率。

索引的数据结构的选择有两个指标:单值查询和范围查询。各个数据结构的查询效率如下:

  1. 数组:单值查询慢,范围查询慢。
  2. 链表:单值查询慢,范围查询慢。
  3. 二叉树:单值查询较慢,范围查询慢。
  4. B树:单值查询较快,范围查询慢。
  5. B+树:单值查询较快,范围查询较快(MySQL官方推荐数据结构)
  6. Hash表:单值查询快,范围查询慢(MySQL内部使用,不开放给用户)

B+树是对B树的一种优化。叶子节点之间维护一个指针,方便了范围查找;所有非叶子节点会在叶子节点中冗余一份,并且自身不再存储数据,而只存储key值,这样就降低了树的高度。

为什么要降低树的高度?因为数据库读取数据时是按树的层序读取,而每一次读取都要经历一次磁盘IO,所以树的高度越低,磁盘IO的次数越少,效率越高。

为什么MySQL使用主键自增策略?因为无序的插入索引会导致树的结构发生较多较大的变化,而改变结构是要消耗时间的。在主键自增的策略下,每次新建的数据的主键索引就永远插入到索引树的右侧,这样就能保证树的结构不会发生较大的改变。

索引是不是声明的越多越好?首先,声明索引需要建立索引树,需要占用空间;其次,每次对数据的增删改都会影响索引树的结构,如果索引树太多势必会导致维护这些索引树的代价提升。所以索引并不是越多越好。

数据库的组成结构

连接器:校验用户名和密码,和客户端建立连接。

分析器:进行语法分析,编译SQL语句。

优化器:优化SQL语句的性能,主要操作为

  1. 选择哪个索引进行查询。
  2. 多表查询时,选择表连接的顺序。

执行器:执行SQL语句编译后的指令。

存储引擎:存储数据。

存储引擎

目前MySQL使用的引擎有MyISAM和InnoDB。

MyISAM:MyISAM有三种文件,分别是表结构定义文件、数据文件和索引文件。因为它的数据和索引是分开存储的,所以MyISAM的索引叫非聚集索引。索引分为两种类型:主键索引和非主键索引,根据索引树是否是由主键生成来区分。在MyISAM中:

  1. 主键索引的key值为主键值,data为数据对应的地址值。
  2. 非主键索引的key值为指定的队列值,data也为数据对应的地址值。

InnoDB:InnoDB有两种文件。分别是表结构定义文件、数据/索引文件。因为它的数据和索引放在一个文件中,所以InnoDB的索引叫聚集索引。在InnoDB中:

  1. 主键索引的key值为主键值,data为主键对应的数据。不同于MyISAM存储的是数据的地址,因为InnoDB存储的是数据本身,这就要求InnoDB必须有一列主键,否则就无法构建索引树。如果用户建表时不声明主键,那么InnoDB会维护一个隐藏列作为主键。MySQL推荐自定义主键的原因就是如果我们不声明主键,我们也无法通过隐藏的索引列来进行查询,这就浪费了主键索引的性能。
  2. 非主键索引的key值为指定的队列值,data为数据对应的主键值。

MyISAM与InnoDB的区别:

  1. InnoDB支持事务,MyISAM不支持事务。
  2. InnoDB支持外键,MyISAM不支持外键。
  3. InnoDB支持表锁和行锁,MyISAM只支持表锁。

那么什么情况下使用MyISAM?因为MyISAM不支持事务,且只支持表锁,会导致增删改查的效率下降,并有发生隔离问题的可能,所以一般存储不需要更改的数据,比如历史数据。

索引语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 查询索引
show index from tableName;

-- 建立索引
create table tableName(
id int PRIMARY KEY,
index idx_name(name) using BTREE
)ENGINE=InnoDB character set utf8;

-- 查看索引
show index from tableName;

-- 删除索引
alter table tableName drop index idx_name;

-- 添加索引
alter table tableName add index idx_name;

回表

回表是指在一次查询中,需要根据非主键索引查询出主键值,再根据主键值在主键索引中找到数据,这样就查询了两条索引树,导致查询的效率变低了。

如何避免回表?主要的方式有:

  1. 尽量使用主键查询。因为只有使用非主键索引才会发生回表。
  2. 尽量避免使用select * from。因为如果准确列出列名,且列名中包含非主键索引,那么该列的值会直接使用非主键索引中的值,而非去使用获得主键,并在主键索引树查询得到的值。
  3. 可以考虑使用联合索引。这样可以降低非主键索引树的高度,能更快的查到主键值。

Maven

Maven是一个项目管理工具,主要功能是编译项目、将项目打包为jar包、依赖管理。

Maven有以下指令:

  • clean:删除编译好的项目文件夹target。
  • validate:验证项目中文件的合法性和权限。
  • compile:编译项目,生成target文件夹。
  • test:可以运行test包下的所有测试方法。
  • package:将项目打包成.jar或.war。
  • verify:验证打包是否有效且合法。
  • install:可以将打包生成的jar包复制到本地仓库中。
  • site:建立远程站点。
  • deploy:把本地仓库传输到远端部署。

依赖管理

scope作用域:在导入依赖时,可以对依赖所影响的作用域进行限制,使用标签即可。

作用域有以下几种:

  • test:仅在test包下有效,在main包下无效。
  • provide:在编译时生效,在运行时失效。主要用于对依赖的版本控制,如对旧依赖使用provide作用域。
  • runtime:在编译时失效,在运行时生效。主要用于面向接口编程时对编程的规范,如JDBC,在使用JDBC的方法时,由于编译时使用的是java自带的接口,运行时才使用导入的驱动包中的实现类,所以此时编译并不会报错,且可以正常运行。
  • compile:默认作用域,作用于全局。

依赖传递:依赖具有传递性。如A依赖引入了B依赖,B依赖引入了C依赖,那么A依赖就一定也会引入C依赖。

依赖冲突:在同一个项目中,导入同一依赖的不同版本,就会发生冲突。冲突的解决方法有:

  1. 声明优先原则:指同一依赖的不同版本中,谁先在pom.xml声明,就优先使用谁。
  2. 就近原则:指在依赖传递时,谁传递的次数比较少,就优先使用谁。就近原则的优先级高于声明优先原则。
  3. 手动排除。
  4. 提取常量。在pom.xml顶部事先提取依赖版本,这样就可以避免依赖冲突。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<properties>
<!--
1. 提取了常量之后,可以避免依赖冲突的问题
2. 提取了常量之后,可以方便我们后期管理这些依赖(查看版本,更换版本)
-->
<spring.version>5.3.3</spring.version>
</properties>

<dependencies>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

</dependencies>

清理Maven

在本地仓库下寻找含有lastupdatedpart关键字的文件,删除之。

Junit

Junit是一种测试工具,可以运行指定的方法。

Junit有以下五种注解:

  1. @Test:单元测试。修饰的方法必须是public void,必须没有参数。
  2. @After:在测试执行后执行。
  3. @Before:在测试执行前执行。
  4. @AfterClass:在测试类类加载前执行。
  5. @BeforeClass:在测试类中的全部方法执行完毕后执行。

其中,@AfterClass、@BeforeClass必须修饰静态方法。

测试类必须放在test包下。

测试类一般命名为XxxTest,测试方法一般命名为testXxx。

Mybatis

Mybatis是一种ORM框架。ORM意为对象关系映射,即是将SQL中的数据转化为Java对象,或是将Java对象转化为SQL记录。Mybatis可以帮我们在Java中更高效的操作数据库。

Mybatis需要一个主配置文件,用于获取SqlSessionFactory。SqlSessionFactory时一个工厂,用于生产SqlSession实例对象。SqlSession是一种Mybatis框架与数据库的连接,里面封装了Connection对象。

配置文件样例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<configuration>

<settings>
<!-- 添加日志的配置 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>

</settings>

<!-- 环境的配置,其实就是去配置数据库连接-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/40th?useSSL=false&amp;characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>


<mappers>
<!--<mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
</mappers>

</configuration>

其中标签用于放置SQL语句的配置文件,一般命名为XxxMapper.xml,并放置于Maven项目中的src/main/resources文件下,且要与src/main/java中的Mapper接口在相同的路径下。

Mapper配置文件样例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper.xml 映射文件中的标签没有顺序要求 -->


<!-- namespace: 命名空间,需要唯一 -->
<mapper namespace="cskaoyan">

<!--<insert id=""-->
<!--<delete id=""-->
<!--<update id=""-->
<!--<select id=""/>-->

<!--
后续如何找到这个标签中的SQL语句呢?
namespace.id = 这个SQL语句的坐标

id: 指这个SQL语句的位置,每一个标签的id不能重复
resultType:结果的类型
-->
<select id="selectAccountById" resultType="com.cskaoyan.bean.Account">
select * from account where id = #{id}
</select>

<select id="selectAccountList" resultType="com.cskaoyan.bean.Account">
select * from account
</select>


</mapper>

Mybatis的动态代理功能可以根据Mapper配置文件和由用户制定的Mapper接口,自动生成接口的代理对象,但是对Mapper接口有如下要求:

  1. 接口的全限定名需与Mapper.xml下的标签中的值保持一致。
  2. 接口的方法要与Mapper.xml下的
×