数据库

2022-06-20  本文已影响0人  bowen_wu

概述

数据库优点

事务

事务是数据库管理系统执行过程中的一个逻辑单元,由一个有限的数据库操作序列构成。具有 ACID 性质

ACID

数据类型

数据结构

数据库数据结构一般为 B+ 树 | B 树

在 B 树中,每一个节点可以有若干个子节点,当数据插入的时候,这些节点会动态的变化,它是一个多叉树

B+ 树更充分的利用了节点的空间,更加稳定 => 引入了从子节点到下一个兄弟节点的指针 => 参考

优点

  1. 多叉树,每一个节点包含多个记录 => 树的高度特别低 => 使得找到一个数据只需要很少的查找次数
  2. 所有的节点都包括范围 => 可以迅速找到头节点和尾节点

索引

在数据之外,MySQL 会维护一个以 Primary Key 为主索引的 B+ 树。如果创建了新的索引,那么将会维护另一个以新的索引的 B+ 树,其中每一个记录都指向了对应的 Primary Key。之后根据新的索引去查找数据,首先执行新的索引,找到后,查到指向的 Primary Key,之后去 Primary Key 索引的 B+ 树上查找,拿到真正的数据,真正的数据可能非常长,索引是很少的一部分数据

联合索引

CREATE INDEX <index_name> ON table_name (column1, column2, ...);

举例

(a, b, c, d) 索引
select * from xx where a = 1 and b = 2 and c > 3 and d = 4;
c > 3 是范围查找,有了范围索引之后,意味着索引用处不大了,只能找到索引,之后把后面的记录都捞出来。查询优化器看到范围索引,就到此为止,将前面的条件试图使用一个联合索引的方式。遇到 c > 3 使用 (a, b) 联合索引会比较快,d = 4 是用不到索引的

上述 d = 4 为啥用不到索引?
答:上述等价于 select * from xx where a = 1 and b = 2 and d = 4 and c > 3,在 (a, b, c, d) 索引内是没有 (a, b, d)
联合索引的。此时可以根据具体业务创建 (a, b, d, c) 联合索引

索引优化原则

最左前缀匹配

在 MySQL 建立联合索引是会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配

倒排索引 => Elasticsearch

传统的关系型数据库按照 id 搜索很快 => 建立了以 id 为索引的 B+ 树 => 相等操作 => 文本是 contain 操作 => B+ 树不适用于文本搜索场景

数据库表设计原则

数据库别名 => alias => 关系型数据库 => 表不仅存储实体的数据,还存储这些实体间的关系 => 例如:订单表维护了用户和商品之间的关系

SQL

基本 SQL

SQL 注意事项

select 基本语句

select 高级语句

inner join vs left join vs right join

JDBC

使用 JDBC 连接数据库

使用 JDBC 从数据库读取数据

注:先确保 SQL 语句正确

SQL 注入

通过把 SQL 命令插入到 Web 表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意代码的 SQL 命令

// Statement
Statement statement = connect.Statement();
String sql = "select * from user where name = '" + username + "' and password = '" + password + "'";
statement.executeQuery(sql);

// PreparedStatement
PreparedStatement statement = connection.prepareStatement("select * from user where name = ? and password = ?");
statement.setString(1, username);
statement.setString(2, password);
statement.executeQuery();

使用 Statement 会在 execute 的时候将 SQL 语句解析为语法树(AST),但是 PrepareStatement 会预先编译 SQL 语句,预先解析 SQL 语句,传入的字符串,不再解析为新的语法树(AST),只是替换原有 SQL 语句中的 ?

MyBatis

configuration

Mapper

<!-- config.xml -->
<mappers>
    <mapper class="org.mybatis.<FQCN>.MyCustomMapper"/>
</mappers>
// MyCustomMapper.java
public interface MyCustomMapper {
    @Delete("delete from USER where id = #{id}")
    void deleteUserById(Integer id);

    @Select("select * from User where id = #{id}")
    User selectUserById(Integer id);
}

// Main.java
public class Main {
    public User selectUserById(Integer id) {
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            MyCustomMapper mapper = sqlSession.getMapper(MyCustomMapper.class);
            return mapper.selectUserById(id);
        }
    }
}

Configuration XML

使用 XML 编写复杂 SQL => 可以方便的使用 MyBatis 的强大功能 => SQL 和代码分离

<!-- config.xml -->
<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
    <select id="selectUser" parameterType="int" resultType="map">
        select * from user
    </select>
</mapper>

parameterType

resultType

动态 SQL

Docker

Empowering App Development for Developers

Docker 安装数据库优点

Docker SQL

// 启动一个 MySQL 实例
docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

// 启动一个 PostgreSQL 实例
docker run --name postgres -p 5432:5432 -e POSEGRES_PASSWORD=123 -d postgres:12
docker rm -f <dockerName>

现在使用 docker 启动的数据库的数据是不持久化的 => 如果容器重启,那么数据库中数据的修改将会丢失 => 除非在启动容器的时候使用 -v 参数 => 将 Docker 容器内的数据文件映射到宿主机上的一个文件上

Example

  1. 创建一个 data 文件夹,用于映射 MySQL 数据库文件
    mkdir mysql-data
    
  2. 启动一个 MySQL 实例
    docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -v `pwd`/mysql-data:/var/lib/mysql -d mysql:8
    
    Docker MySQL 实例
  3. 使用 IDEA JDBC 连接数据库


    Data Sources and Drivers
    • 此时 MySQL 中没有 Database,需要连接上之后手动创建
    • 可以点击 Test Connection 尝试连接
      Test Connection
  4. 创建 Database => create database <database_name>
  5. 使用 Flyway 进行相关数据的迁移
    <!-- pom.xml -->
    <plugin>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-maven-plugin</artifactId>
        <version>7.13.0</version>
        <configuration>
            <url>jdbc:mysql://localhost:3306/mall?characterEncoding=utf-8</url>
            <user>root</user>
            <password>123456</password>
        </configuration>
        <executions>
            <execution>
                <id>init</id>
                <phase>initialize</phase>
                <goals>
                    <goal>migrate</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    
    <!--  Terminal => 需要有 migration https://flywaydb.org/documentation/getstarted/firststeps/maven#creating-the-first-migration  -->
    <!--  mvn flyway:migrate  -->
    

知识点

  1. 主键最好不要用可能会修改的值
  2. 外键 => 一个表的某个列是其他表的主键
  3. 数据库是天然的线程安全的,不需要额外的同步
  4. select 之后根据拿出来的结果进行判断是否要 delete => 不是原子操作
  5. insert 是原子操作
  6. MySQL 的 charset utf8mb4 是真正的 utf8
  7. 当 SQL 运行特别慢的时候,通过一些性能分析,进行相应优化 => explain
  8. Error => expected "identifier"; => SQL 语句有关键字
  9. DDL => Data Definition Language => 数据定义语言
  10. 删除
    • 物理删除 => 数据被从数据库中抹去了
    • 逻辑删除 => 数据还在数据库中,只是我们假装看不见而已
上一篇下一篇

猜你喜欢

热点阅读