文章目录
-
-
- [1. 什么是MySQL?](#1. 什么是MySQL?)
- [2. 关系型数据库和非关系型数据库](#2. 关系型数据库和非关系型数据库)
- [3. 数据库三大范式是什么?](#3. 数据库三大范式是什么?)
- [4. 一条 SQL 查询语句是如何执行的](#4. 一条 SQL 查询语句是如何执行的)
- [5. 引擎](#5. 引擎)
- [6. 索引16连问](#6. 索引16连问)
- [7. 事务](#7. 事务)
- [8. MySQL有哪些锁?](#8. MySQL有哪些锁?)
- [9. 什么是死锁?怎么解决?](#9. 什么是死锁?怎么解决?)
- [10. 数据库的乐观锁和悲观锁是什么?怎么实现的?](#10. 数据库的乐观锁和悲观锁是什么?怎么实现的?)
- [11. MVCC 知道吗?(Multiversion concurrency control)](#11. MVCC 知道吗?(Multiversion concurrency control))
- [12. 快照读和当前读](#12. 快照读和当前读)
- [13. 说说count(1)、count(*)和count(字段名)的区别](#13. 说说count(1)、count(*)和count(字段名)的区别)
- [14. truncate、delete与drop区别?](#14. truncate、delete与drop区别?)
- [15. 视图](#15. 视图)
- [16. SQL优化](#16. SQL优化)
- [17. 数据库优化](#17. 数据库优化)
- [18. 使用JDBC操作数据库的步骤](#18. 使用JDBC操作数据库的步骤)
-
1. 什么是MySQL?
MySQL是一个关系型数据库,它采用表的形式来存储数据。你可以理解成是Excel表格,既然是表的形式存储数据,就有表结构(行和列)。行代表每一行数据,列代表该行中的每个值。列上的值是有数据类型的,比如:整数、字符串、日期等等。
2. 关系型数据库和非关系型数据库
- 关系型数据库指的是使用关系模型(二维表格模型)来组织数据的数据库。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。
- 非关系型数据库又被称为 NoSQL(Not Only SQL ),意为不仅仅是 SQL。通常指数据以对象的形式存储在数据库中,而对象之间的关系通过每个对象自身的属性来决定,常用于存储非结构化的数据。
3. 数据库三大范式是什么?
- 第一范式:每个列都不可以再拆分。
- 第二范式:在第一范式的基础上,要求非主键列完全依赖于主键,而不能是依赖于主键的一部分。
- 第三范式:在第二范式的基础上,要求非主键列只依赖于主键,不依赖于其他非主键。
在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计。
4. 一条 SQL 查询语句是如何执行的
- MySQL 客户端与服务器间建立连接,客户端发送一条查询给服务器;
- 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果;否则进入下一阶段;
- 服务器端进行 SQL 解析、预处理,生成合法的解析树;
- 再由优化器生成对应的执行计划;
- MySQL 根据优化器生成的执行计划,调用相应的存储引擎的 API 来执行,并将执行结果返回给客户端。
5. 引擎
MySQL存储引擎MyISAM与InnoDB区别
- Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。
- MyIASM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键。
- MEMORY引擎:所有的数据都在内存中,数据的处理速度快,但是安全性不高。
MyISAM索引与InnoDB索引的区别?
- InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
- InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。
- MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。
- InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效。
InnoDB引擎的4大特性
- 插入缓冲(insert buffer)
- 二次写(double write)
- 自适应哈希索引(ahi)
- 预读(read ahead)
6. 索引16连问
什么是索引?
- 索引是存储引擎用于提高数据库表的访问速度的一种数据结构。它可以比作一本字典的目录,可以帮你快速找到对应的记录。
- 索引一般存储在磁盘的文件中,它是占用物理空间的。
索引的优缺点?
优点:
- 加快数据查找的速度, 加快表与表之间的连接
- 为用来排序或者是分组的字段添加索引时,可以加快分组和排序的速度
缺点:
- 建立索引需要占用物理空间
- 会降低表的增删改的效率,因为每次对表记录进行增删改,需要进行动态维护索引,导致增删改时间变长
索引的作用?
由于数据是存储在磁盘上的,查询数据时,如果没有索引,会加载所有的数据到内存,依次进行检索,读取磁盘次数较多。有了索引,就不需要加载所有数据,因为B+树的高度一般在2-4层,最多只需要读取2-4次磁盘,查询速度大大提升。
索引设计的原则?
- 适合索引的列是出现在where子句中的列,或者连接子句中指定的列
- 基数较小的类,索引效果较差,没有必要在此列建立索引
- 使用短索引(前缀索引),如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间
- 不要过度使用索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。
什么情况下需要建索引?
- 经常用于查询的字段
- 经常用于连接的字段建立索引,可以加快连接的速度
- 经常需要排序的字段建立索引,因为索引已经排好序,可以加快排序查询速度
什么情况下不建索引?
- where条件中用不到的字段不适合建立索引
- 表记录较少。比如只有几百条数据,没必要加索引。
- 需要经常增删改。需要评估是否适合加索引
- 参与列计算的列不适合建索引
- 区分度不高的字段不适合建立索引,如性别,只有男/女/未知三个值。加了索引,查询效率也不会提高。
索引有哪几种底层实现?(索引的数据结构/为什么B+树比B树更适合实现数据库索引?)
哈希索引
:哈希索引是基于哈希表实现的,对于每一行数据,存储引擎会对索引列进行哈希计算得到哈希码,并且哈希算法要尽量保证不同的列值计算出的哈希码值是不同的,将哈希码的值作为哈希表的key值,将指向数据行的指针作为哈希表的value值。这样查找一个数据的时间复杂度就是O(1),一般多用于精确查找
B 树索引
:B 树的特点就是节点同时保存 key 和 数据,B 树在找到具体的数值以后就结束,查询复杂度不稳定,最好为 O(1),数据就在第一层(所以 B 树适合把热点数据存在上层,适用于缓存)
B+ 树索引
:B+ 树的特点是非叶子节点只保存 key,而叶子节点保存 key 和 数据
- 并且各叶子节点之间通过双向链表按照大小进行连接。也就是说,B+ 树的叶子节点存储真正的记录,而非叶子节点的存在是为了更快速的找到对应记录所在的叶子节点。所以时间复杂度稳定,每次都需要走到叶子节点,它的时间复杂度为 O(LogN)。
- 并且由于所有数据都在叶子节点且顺序连接,所以 B+ 树可使用在范围查询,而 B 树无法进行范围查询
- B+ 树的叶子节点并不是只存一行数据,而是存一页数据!每个页面中有很多行记录
- 所以InnoDB 不是按行的来操作的,它可操作的最小粒度是页,页加载进内存后才会通过扫描页来获取行记录。
索引有什么分类?
主键索引
:数据列不允许重复,不允许为NULL,一个表只能有一个主键。唯一索引
:索引列中的值必须是唯一的,但是允许为空值。唯一索引和主键索引的区别是:唯一索引字段可以为null且可以存在多个null值,而主键索引字段不可以为null。唯一索引的用途:唯一标识数据库表中的每条记录,主要是用来防止数据重复插入。组合索引
:也叫联合索引,在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时需遵循最左前缀原则。全文索引
:只能在char、varchar和text类型字段上使用全文索引。普通索引
:普通索引是最基本的索引,它没有任何限制,值可以为空。
什么是最左前缀原则?什么是最左匹配原则?
最左前缀原则
是指在创建多列索引时,要根据业务需求,把where子句中使用最频繁的一列放在最左边。最左匹配原则
指的是 SQL 语句中用到了组合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个组合索引去进行匹配。当遇到范围查询(>、<、between、like)就会停止匹配,后面的字段不会用到索引。- 对(a,b,c)建立索引,查询条件使用 a/ab/abc 会走索引,使用 bc 不会走索引。
- 对(a,b,c,d)建立索引,查询条件为a = 1 and b = 2 and c > 3 and d = 4,那么a、b和c三个字段能用到索引,而d无法使用索引。因为遇到了范围查询。
聚集索引和辅助索引
聚集索引是按照数据在磁盘上的物理顺序来组织数据的,其叶子节点保存着完整的数据行信息
。在InnoDB 中,如果表定义了主键,则主键索引是聚集索引;如果表没有定义主键,则第一个唯一非空索引是聚集索引;如果都没有,则 InnoDB 会隐式创建一个隐藏的聚集索引。辅助索引也称为 非聚集索引、二级索引
。其叶子节点保存着索引字段和指向对应数据行的指针(相当于主键 ID),通过这个指针可以找到对应的数据行。在查询中,如果使用的是非聚集索引,则需要先根据索引查找到对应的行指针,再通过行指针查找数据行,这个过程叫做回表查询,因此他的查询速度相对于聚集索引要慢一些。
非聚集索引(二级索引)一定会回表查询吗?
- 不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。
- 举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。
联合索引是什么?为什么需要注意联合索引中的顺序?
MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。
什么是覆盖索引
覆盖索引的目的就是避免发生回表查询,通过覆盖索引,只需要扫描一次 B+ 树即可获得所需的行记录,也就是说当前查询语句所要求的字段全部命中了二级索引中所保存的索引字段。
什么是前缀索引
- 前缀索引是一种数据库优化技术,它只使用列值的一部分去作为索引的键值。
- 通常用于字符类型的列,特别是当列的长度很长时。如果一个列值的前缀(例如前5个字符)在识别记录方面足够唯一时,我们就可以只使用这部分值来创建索引。这样做可以减小索引的大小,从而节省存储空间,提高查询速度。
使用前缀索引可能会导致两个问题:
- 可能会增加记录扫描次数与回表次数,影响性能。针对这一点呢,其实前缀索引长度的选取还是很重要的,可能前缀定义的长一点,就能够大幅减少记录扫描次数和回表次数
- 使用前缀索引其实就没法用覆盖索引对查询性能的优化了,因为 InnoDB 并不能确定前缀索引的定义是否截断了完整信息,就算是完全踩中了前缀索引,InnoDB 还得回表确认一次到底是不是满足条件了
索引什么时候会失效?
- 对于组合索引,不是使用组合索引最左边的字段,则不会使用索引
- 以%开头的like查询如%abc,无法使用索引;非%开头的like查询如abc%,相当于范围查询,会使用索引
- 查询条件中列类型是字符串,没有使用引号,可能会因为类型不同发生隐式转换,使索引失效
- 判断索引列是否不等于某个值时
- 对索引列进行运算
- 查询条件使用or连接,也会导致索引失效
什么是索引下推
- 索引下推是MySQL5.6新添加的特性,用于优化数据的查询。
- 而 MySQL 5.6 开始,数据库在取出索引的同时,会根据 where 条件直接过滤掉不满足条件的记录,减少回表次数。这就是 索引下推
当存在索引的列做为判断条件时,MySQL server将这一部分判断条件传递给存储引擎,然后存储引擎会筛选出符合MySQL server传递条件的索引项,即在存储引擎层根据索引条件过滤掉不符合条件的索引项,然后回表查询得到结果,将结果返回给MySQL server。
可以看到,有了索引下推的优化,在满足一定的条件下,存储引擎层会在回表查询之前对数据进行过滤,可以减少存储引擎回表查询的次数。
7. 事务
什么是数据库事务?
事务其实就是封装的一组操作,要么都执行,要么都不执行
事务的四大特性(ACID)介绍一下?
事务的特性ACID:原子性、一致性、隔离性、持久性。
原子性
:指事务包含的所有操作要么全部成功,要么全部失败回滚。一致性
:是指一个事务执行之前和执行之后都必须处于一致性状态。比如在转账业务中,无论事务是否成功,转账人和收款人的总额应该是不变的。- 隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,每个并发事务之间的数据库是独立的;
持久性
:指一个事务一旦被提交了,对数据库中数据的修改就是永久的,即便系统故障也不会丢失。
什么是脏读?幻读?不可重复读?
- 脏读是指一个事务能够读取另一个未提交事务的修改。如果那个未提交的事务最后回滚了,那么第一个事务所读取的数据就是不准确的,也称之为"脏数据"。
- 幻读指的是在同一个事务中,多次执行相同的查询,但是每次查询返回的行数却不同,这是因为在这个事务读取数据的期间,其他事务插入了新的数据所导致的。
- 不可重复读指的是在同一个事务中,多次读取同一行数据,但是每次读取的结果都不同,这是因为在这个事务读取数据的期间,其他事务修改了这些数据所导致的;
不可重复读和脏读有什么区别?
脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
不可重复读和幻读有什么区别?
不可重复读主要涉及到修改数据,而幻读则主要涉及到插入或删除数据。
解决方案不同:不可重复读的解决方案通常是使用行锁或者表锁来解决,而幻读的解决方案通常是使用间隙锁来解决。
事务的隔离级别有哪些?
Serializable (串行化)
:通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。Repeatable read (可重复读)
:MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行,解决了不可重复读的问题。Read committed (读已提交)
:一个事务只能看见已经提交事务所做的改变。可避免脏读的发生。Read uncommitted (读未提交)
:所有事务都可以看到其他未提交事务的执行结果。
查看隔离级别
:select @@transaction_isolation;
设置隔离级别
:set session transaction isolation level read uncommitted;
生产环境数据库一般用的什么隔离级别呢?
生产环境大多使用RC(读已提交)。为什么不是RR(可重复读)呢?
读已提交(Read Commited),简称为RC
, 可重复读(Repeatable Read),简称为RR
- 缘由一:在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多!
- 缘由二:在RR隔离级别下,条件列未命中索引会锁表!而在RC隔离级别下,只锁行!
也就是说,RC的并发性高于RR。并且大部分场景下,不可重复读问题是可以接受的。毕竟数据都已经提交了,读出来本身就没有太大问题!
8. MySQL有哪些锁?
按锁粒度分类,有行级锁、表级锁和页级锁
行级锁是mysql中锁定粒度最细的一种锁
。表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但加锁的开销也最大。行级锁的类型主要有三类:- Record Lock,记录锁,也就是仅仅把一条记录锁上;
- Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身;
- Next-Key Lock:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。
表级锁是mysql中锁定粒度最大的一种锁
,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用的MyISAM与InnoDB都支持表级锁定。页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁
。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。
按锁级别分类,有共享锁、排他锁和意向锁。
共享锁又称读锁,是读取操作创建的锁。
其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。排他锁又称写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。
获准排他锁的事务既能读数据,又能修改数据。- 意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。
InnoDB 中的两个表锁
:意向共享锁(IS)
:表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁;意向排他锁(IX)
:类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。- 意向锁是 InnoDB 自动加的,不需要用户干预。
9. 什么是死锁?怎么解决?
- 死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。
常见的解决死锁的方法
- 如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。
- 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
- 对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率
10. 数据库的乐观锁和悲观锁是什么?怎么实现的?
- 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。
- 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制
乐观锁适用于读多写少的场景,悲观锁就比较合适写多的场景
11. MVCC 知道吗?(Multiversion concurrency control)
MVCC 就是同一份数据保留多版本的一种方式,进而实现并发控制。在查询的时候,通过read view和版本链找到对应版本的数据。
作用:提升并发性能。对于高并发场景,MVCC比行级锁开销更小。
12. 快照读和当前读
快照读
:读取的是快照版本。普通的select就是快照读。通过mvcc来进行并发控制的,不用加锁。当前读
:读取的是最新版本。update、delete、insert、select ... lock in share mode、select ... for update是当前读。
快照读情况下,InnoDB通过mvcc机制避免了幻读现象。而mvcc机制无法避免当前读情况下出现的幻读现象。因为当前读每次读取的都是最新数据,这时如果两次查询中间有其它事务插入数据,就会产生幻读。
13. 说说count(1)、count(*)和count(字段名)的区别
- count(*)包括了所有列,相当于行数,在统计结果的时候,不会忽略列值为NULL
- count(1)包括了所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL
- count(字段名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是指空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计
14. truncate、delete与drop区别?
- 不再需要一张表的时候,用drop;
- 想删除部分数据行时候,用delete;
- 想保留表同时想删除所有数据的时候用truncate。
15. 视图
为什么要使用视图?什么是视图?
- 为了提高复杂SQL语句的复用性和表操作的安全性,MySQL数据库管理系统提供了视图特性。所谓视图,本质上是一种虚拟表,在物理上是不存在的,其内容与真实的表相似,包含一系列带有名称的列和行数据。但是,视图并不在数据库中以储存的数据值形式存在。行和列数据来自定义视图的查询所引用基本表,并且在具体引用视图时动态生成。
- 视图使开发者只关心感兴趣的某些特定数据和所负责的特定任务,只能看到视图中所定义的数据,而不是视图所引用表中的数据,从而提高了数据库中数据的安全性。
视图的优点
- 查询简单化。视图能简化用户的操作
- 数据安全性。视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护
- 逻辑数据独立性。视图对重构数据库提供了一定程度的逻辑独立性
16. SQL优化
说出一些数据库优化方面的经验?
- 有外键约束的话会影响增删改的性能,如果应用程序可以保证数据库的完整性那就去除外键
- Sql语句全部大写,特别是列名大写,因为数据库的机制是这样的,sql语句发送到数据库服务器,数据库首先就会把sql编译成大写在执行,如果一开始就编译成大写就不需要了把sql编译成大写这个步骤了
- 如果应用程序可以保证数据库的完整性,可以不需要按照三大范式来设计数据库
- 其实可以不必要创建很多索引,索引可以加快查询速度,但是索引会消耗磁盘空间
- 如果是jdbc的话,使用PreparedStatement不使用Statement,来创建SQl,PreparedStatement的性能比Statement的速度要快,使用PreparedStatement对象SQL语句会预编译在此对象中,PreparedStatement对象可以多次高效的执行
怎么优化SQL查询语句吗
- 对查询进行优化,应尽量
避免全表扫描
,首先应考虑在 where 及 order by 涉及的列上建立索引 - 用
索引
可以提高查询 - SELECT子句中
避免使用*号
,尽量全部大写SQL,数据库会把sql编译成大写在执行,如果一开始就编译成大写就不需要把sql编译成大写这个步骤了 - 应尽量
避免在 where 子句中对字段进行 is null 值判断
,否则将导致引擎放弃使用索引而进行全表扫描,使用 IS NOT NULL where 子句中使用 or 来连接条件
,也会导致引擎放弃使用索引而进行全表扫描in 和 not in 也要慎用
,否则会导致全表扫描
你怎么知道SQL语句性能是高还是低?
- 通过慢查询日志去查看SQL的执行时间
- 可以通过 Explain 命令来查看 MySQL 执行 SQL 语句的详细执行计划,包括表的读取顺序、使用的索引、扫描行数、连接类型等信息,通过这些信息可以找到 SQL 语句执行缓慢的原因。
如何定位及优化SQL语句的性能问题?创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?
对于低性能的SQL语句的定位,最重要也是最有效的方法就是使用执行计划
,MySQL提供了explain命令来查看语句的执行计划。对于查询语句,最重要的优化方式就是使用索引。 而执行计划,就是显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等。
通过type 访问类型可以看到有没有走索引
- ALL 扫描全表数据
- index 遍历索引
- range 索引范围查找
- index_subquery 在子查询中使用 ref
- unique_subquery 在子查询中使用 eq_ref
- ref_or_null 对Null进行索引的优化的 ref
- fulltext 使用全文索引
- ref 使用非唯一索引查找数据
- eq_ref 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联
大表数据查询慢,怎么优化?
- 在合适的字段上
建立索引
优化查询速度 利用缓存
,利用Redis等缓存热点数据,提高查询效率读写分离
,主库负责写,从库负责读限定数据的范围
。比如:用户在查询历史信息的时候,可以控制在一个月的时间范围内冷热数据分离
。几个月之前不常用的数据放到冷库中,最新的数据比较新的数据放到热库中- 通过
分库分表
的方式进行优化,主要有垂直拆分和水平拆分
垂直拆分
:是指数据表列的拆分,把一张列比较多的表拆分为多张表,比如,用户表中一些字段经常被访问,将这些字段放在一张表中,另外一些不常用的字段放在另一张表中,插入数据时,使用事务确保两张表的数据一致性。垂直拆分的原则
:- 把不常用的字段单独放在一张表;
- 把 text,blob 等大字段拆分出来放在附表中;
- 经常组合查询的列放在一张表中。
水平拆分
:指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。通常情况下,我们使用取模的方式来进行表的拆分,比如,一张有 400W 的用户表 users,为提高其查询效率我们把其分成 4 张表 users1,users2,users3,users4,然后通过用户 ID 取模的方法,同时查询、更新、删除也是通过取模的方法来操作。
慢查询日志
用于记录执行时间超过某个临界值的SQL日志,用于快速定位慢查询,为我们的优化做参考。
17. 数据库优化
为什么要优化
- 系统的吞吐量瓶颈往往出现在数据库的访问速度上
- 随着应用程序的运行,数据库的中的数据会越来越多,处理时间会相应变慢
- 数据是存放在磁盘上的,读写速度无法和内存相比
优化原则:减少系统瓶颈,减少资源占用,增加系统的反应速度。
MySQL数据库cpu飙升到500%的话他怎么处理?
- 当 cpu 飙升到 500%时,
先用操作系统命令 top 命令
观察是不是 mysqld 占用导致的,如果不是,找出占用高的进程,并进行相关处理。 - 如果是 mysqld 造成的, show processlist,
看看里面跑的 session 情况
,是不是有消耗资源的 sql 在运行。找出消耗高的 sql
,看看执行计划是否准确, index 是否缺失,或者实在是数据量太大造成。 - 一般来说,肯定要
kill 掉这些线程
(同时观察 cpu 使用率是否下降),等进行相应的调整(比如说加索引、改 sql、改内存参数)之后,再重新跑这些 SQL。 - 也有可能是每个 sql 消耗资源并不多,但是突然之间,
有大量的 session 连进来导致 cpu 飙升
,这种情况就需要跟应用一起来分析为何连接数会激增,再做出相应的调整,比如说限制连接数等
分库分表是怎么做的?
垂直分库
:
- 按业务模块将不同的表分布在不同的数据库中。
- 每个数据库管理某一部分业务模块的所有数据。
- 有助于降低单一数据库的访问和存储压力。
- 适用于各业务模块之间相对独立的场景。
水平分库
:
- 将同一张表的数据按照某个键的值(如用户ID、时间等)分布到不同的数据库中。
- 每个数据库存储表的一部分数据。
- 有助于分散大表的查询和维护压力。
- 适用于单表数据量非常大的场景。
垂直分表
:
- 将一张表按列拆分成多个表,每个表包含部分列。
- 有助于降低单一表的宽度,提高查询效率。
- 适用于某些列被频繁访问,而其他列访问较少的场景。
水平分表
:
- 将一张表按某个键的值(如用户ID、时间等)拆分成多个表,每个表存储部分行。
- 有助于降低单一表的查询和维护压力。
- 适用于单表行数非常多的场景。
18. 使用JDBC操作数据库的步骤
- 创建数据库连接池DataSource
- 使用DataSource获取数据库连接Connection
- 编写SQL语句
- 创建操作命令对象:
- 使用预编译的SQL和占位符时,使用Connection创建PreparedStatement对象。
- 不使用预编译的SQL时,使用Connection创建Statement对象。
- (如果使用PreparedStatement)替换占位符:设置预编译SQL中的参数值。
- 执行SQL:使用Statement或PreparedStatement执行SQL。
- (如果是查询操作)处理结果集ResultSet:遍历和解析查询返回的结果集。
- 释放资源
- 关闭结果集(如果有查询操作)。
- 关闭Statement或PreparedStatement。
- 关闭连接(如果不使用连接池)或将连接返回到连接池。