目录
- sql的执行顺序
- 索引的优点和缺点
- 怎么避免索引失效(也属于sql优化的一种)
- 一条sql查询非常慢,我们怎么去排查和优化?
- 存储引擎 MylSAM和InnoDB、Memory的区别
- 事务的四大特性(ACID)
- 脏读、不可重复读、幻读
- 事务的隔离级别?
- 怎么优化数据库
- SQL优化
- 大表数据查询,怎么优化
- 常用的聚合函数
- 13. 百万级别或以上的数据如何删除
- 锁
- 对MySQL的锁了解吗
- 隔离级别与锁的关系
- 按照锁的粒度分数据库锁有哪些?锁机制与InnoDB锁算法
- 从锁的类别上分MySQL都有哪些锁呢?像上面那样子进行锁定岂不是有点阻碍并发效率了
- MySQL中InnoDB引擎的行锁是怎么实现的?
- 什么是死锁?怎么解决?
- 系列文章
- 版本记录
sql的执行顺序
⑧select ⑨distinct(去重) ⑥聚合函数①from 表1③[inner join | left join | right join](连接) 表2②on(连接条件) 表1.字段 = 表2.字段④where 查询条件⑤group by(分组) 字段⑦having 分组过滤条件⑩order by(排序) 字段⑪limit(分页) 0,10
索引的优点和缺点
优点:
①提高检索的速度。
②索引列对数据排序,降低排序成本。
③mysql 8之后引入了,隐藏索引,当一个索引被隐藏就不会被优化器所使用,就可以看出来索引对数据库的影响,有利于调优。
缺点:
①索引也是一个文件,所以会占用空间。
②降低更新的速度,因为不光要更新数据,还要更新索引。
怎么避免索引失效(也属于sql优化的一种)
①某列使用范围查询(>、<、like、between and)时, 右边的所有列索引也会失效。
②不要对索引字段进行运算。
③在where子句中不要使用 OR、!=、<>和对值null的判断。
④避免使用’%'开头的like的模糊查询。
⑤字符串不加单引号,造成索引失效。
一条sql查询非常慢,我们怎么去排查和优化?
排查:
(1) 开启慢查询。
(2) 查看慢查询日志(定位低效率sql,命令:show processlist)。
(3) 使用explain查看sql的执行计划(看看索引是否失效或者性能低)
优化:
sql优化 + 索引 + 数据库结构优化 + 优化器优化
存储引擎 MylSAM和InnoDB、Memory的区别
MylSAM: mysql5.5之前的存储引擎,是表锁(悲观锁)级别的,不支持事务和外键。
InnoDB: mysql5.5之后的存储引擎,是行锁(乐观锁)级别的,支持事务和外键。
Memory: 内存数据库引擎,因为在内存操作,所以读写很快,但是Mysql服务重启,会丢失数据,不支持事务和外键。
事务的四大特性(ACID)
原子性(Atomicity): 要么全部成功要么全部失败。
一致性(Consistency): 事务执行前和事务执行后,原本和数据库一致的数据仍然一致。
隔离性(Isolation): 事务与事务之间互不干扰。
持久性(Durability): 事务一旦被提交了,那么对数据库中的数据的改变就是永久的。
脏读、不可重复读、幻读
脏读: 也叫"读未提交",顾名思义,就是某一事务A读取到了事务B未提交的数据。
不可重复读: 在一个事务内,多次读取同一个数据,却返回了不同的结果。实际上,这是因为在该事务间隔读取数据的期间,有其他事务对这段数据进行了修改,并且已经提交,就会发生不可重复读事故。
幻读: 在同一个事务中,第一次读取到结果集和第二次读取到的结果集不同。像幻觉一样所以叫幻读。
从上面可以看出脏读和不可重复读是基于数据值的错误,幻读是基于条数增加或者减少的错误
事务的隔离级别?
① read uncommited(读取未提交内容): 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。读取未提交的数据,也被称之为脏读(Dirty Read)
② read committed(读取提交内容): 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。一个事务只能看见已经提交事务所做的改变。可解决脏读
③ repeatable read(可重读): 这是MySQL的默认事务隔离级别,同一事务的多个实例在并发读取数据时,会看到同样的数据。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。可解决脏读、不可重复读
④ serializable(可串行化) : 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。可解决脏读、不可重复读、幻读。
怎么优化数据库
①SQL优化
②加缓存
③分表
④读写分离
SQL优化
①不要用select *,要使用具体字段。
②使用数值代替字符串,比如:0=唱,1=跳,2=rap。
③避免返回大量数据,采用分页最好。
④使用索引,提升查询速度,不宜建太多索引,不能建在重复数据比较多的字段上。
⑤批量插入比单条插入要快,因为事务只需要开启一次,数据量太小体现不了。
⑥避免子查询,优化为多表连接查询。
⑦尽量使用union all替代union,因为union会自动去重。
大表数据查询,怎么优化
- 优化shema、sql语句+索引;
- 加缓存,memcached, redis;
- 主从复制,读写分离;
- 垂直拆分,根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统;
- 水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key, 为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表;
常用的聚合函数
①sum(列名) 求和
②max(列名) 最大值
③min(列名) 最小值
④avg(列名) 平均值
⑤first(列名) 第一条记录
⑥last(列名) 最后一条记录
⑦count(列名) 统计记录数不包含null值 count(*)包含null值。
drop、truncate、delete的区别
速度: drop > truncate > delete。
回滚: delete支持,truncate和drop不支持。
删除内容: delete表结构还在,删除部分或全部数据,不释放空间。truncate表结构还在,删除全部数据,释放空间。drop表结构和数据不在,包括索引和权限,释放空间。
13. 百万级别或以上的数据如何删除
关于索引:由于索引需要额外的维护成本,因为索引文件是单独存在的文件,所以当我们对数据的增加,修改,删除,都会产生额外的对索引文件的操作,这些操作需要消耗额外的IO,会降低增/改/删的执行效率。所以,在我们删除数据库百万级别数据的时候,
查询MySQL官方手册得知删除数据的速度和创建的索引数量是成正比的。
- 1.先删除索引(此时大概耗时三分多钟)
- 2.然后删除其中无用数据(此过程需要不到两分钟)
- 3.重新创建索引(此时数据较少了创建索引也非常快,约十分钟左右。)
与之前的直接删除绝对是要快速很多,更别说万一删除中断,一切删除会回滚。那更是坑了。
锁
对MySQL的锁了解吗
当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。
就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用。
隔离级别与锁的关系
在Read Uncommitted级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突
在Read Committed级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁;
在Repeatable Read级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。
SERIALIZABLE 是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。
按照锁的粒度分数据库锁有哪些?锁机制与InnoDB锁算法
在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。
MyISAM和InnoDB存储引擎使用的锁:
MyISAM采用表级锁(table-level locking)。
InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
行级锁,表级锁和页级锁对比
行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。
特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
表级锁 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
页级锁 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
从锁的类别上分MySQL都有哪些锁呢?像上面那样子进行锁定岂不是有点阻碍并发效率了
从锁的类别上来讲,有共享锁和排他锁。
共享锁: 又叫做读锁。当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加上多个。
排他锁: 又叫做写锁。当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。
用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的。一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以。
锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁。
他们的加锁开销从大到小,并发能力也是从大到小。
MySQL中InnoDB引擎的行锁是怎么实现的?
答:InnoDB是基于索引来完成行锁
例:
select * from tab_with_index where id = 1 for update;
for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,如果 id 不是索引键那么InnoDB将完成表锁,并发将无从谈起
什么是死锁?怎么解决?
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。
常见的解决死锁的方法
1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。
2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;
如果业务处理不好可以用分布式事务锁或者使用乐观锁
系列文章
内容 | 地址 链接 |
---|---|
JAVA面试 | Spring知识点 |
JAVA面试 | 常见问题-超详细 |
JAVA面试 | Redis常见问题 |
版本记录
- 2023-10-18 第一版