一.MySql基础
1.on和where的区别
- 同时存在时,on先执行,where后执行;
- on是生成临时表使用的条件,无论on后的条件是否为真,都会返回对于连接方式对应表的全部数据,如:left join...on总是返回左表所有数据,right join...on总是返回右表所有数据,inner join...on只会生成满足条件的临时表,返回结果和where一致;
- where是先进行表连接,在进行筛选,只会返回满足条件的数据;
2.count(1),count(字段名),count(*)的区别
- count(1):返回满足条件的记录数,不忽略null。InnoDB遍历整张表,不取值。sever对于返回的每一行,放一个1进去,判断当然不可能为null,按行累加;
- count(字段名):一行行读取字段值,判断不为null则累加,返回满足条件的字段记录数;
- cout(*):自动优化到某个字段,不取值,不忽略null,返回满足条件的字段记录数;
3.MySQL存储引擎
- InnoDB:索引结构为B+Tree
- MyISAM:默认引擎,索引结构为B+Tree
4.索引是怎样的数据结构
索引的数据结构与存储引擎有关,常见的索引数据结构有hash索引与B+Tree。
二.SQL优化
1.避免全局扫描
- 任何时候都不要使用select *
2.创建索引
创建索引: CREATE INDEX index_name ON table_name(column_list); ALTER TABLE table_name ADD INDEX index_name(column_list); 删除索引: DROP INDEX index_name ON table_name; ALTER TABLE table_name DROP INDEX index_name;
- 数据量大(300条记录以上)的表需要创建索引
- 作为where后的条件筛选字段应创建索引
- 作为order by后面的排序字段应创建索引
- 作为多表连接中的关联字段应创建索引
- 表数据量小的表不适合创建索引
- 频繁更新的字段不适合创建索引
- 数据分布均匀,唯一性差的字段(性别,布尔类型)不适合创建索引
3.防止索引失效
- 使用or会导致索引失效,解决方法:使用union all或union(推荐用union all,因为union将两个结果合并后还有一个去重操作,增加了运算量与时间)替换or
- like模糊查询%(%xx或者%xx%)开头会导致索引失效,解决方法:使用xx%
- 索引字段有参与逻辑运算(!=,is null,in等)会导致索引失效,
- 发生类型转换的字段会导致索引失效(如:select xx from table where str = 12,str是一个字符串字段,使用12数字会导致先进行数字到字符串的转换,这会导致索引失效,所以一定要用'12'这么写),解决方法:使用与之匹配的类型进行匹配,避免类型转换
- 复合索引遵循“最左原则”,跨列或无序搜索时会导致索引失效,如“复合索引index(a,b,c),查询时acb,bca,bc等都不会走索引,而abc,ab,a会走索引”
- mysql判断全表扫描更快时不会走索引(数据量小)
三.MySQL事务
1.事务的4大特性
- 原子性:一个事务的一系列操作要么做,要么不做,整个过程是一个不可切分的整体,如果中途执行发生了错误,则会回滚到执行前的初始状态;
- 一致性:事务执行后对数据库的完整性没有造成破坏。表明事务写入的数据符合数据库预设规则;
- 隔离性:数据库允许多个事务并发对数据进行操作,隔离性预防了多个事务并发时交叉执行导致的数据不一致。事务的隔离级别有:读未提交,读提交,可重复读,串行化
- 持久性:事务执行完毕后对数据库的改变是永久的,即使系统故障也不会丢失。
2、事务的隔离级别
隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read) 读未提交(Read uncommitted) 可能 可能 可能 读提交(Read committed) 不可能 可能 可能 可重复读(Repeatable read) 不可能 不可能 可能 串行化(Serializable ) 不可能 不可能 不可能
脏读:一个事务访问某一个数据,并对其修改,但修改还未提交到数据库,此时另一个事务也访问了这个数据,读取到了这个还未提交到数据库的数据,并使用了这个数据;
不可重复读:一个事务需要读取一个数据多次,在中途的时候,另一个事务也访问并修改了这个数据,导致前一个事务前后读取到的数据不一致;
幻读:一个事物对表中所有行进行某些修改,这时另一个事务进来往表中添加了新数据记录,导致前一个事务操作者发现表中还有未修改的数据行,好像发生了幻觉。
四.Redis知识点
基于内存的高性能Nosql数据库。
1.Redis支持的数据类型
- 字符串String:
- 哈希Hash:
- 数组List:
- 集合Set:
- 有序集合Zset:
2.什么是Redis持久化?Redis有哪几种持久化方式?
- 持久化:将数据写到磁盘保存,防止系统宕机内存数据丢失。
- RDB(Redis DataBase):两个核心函数rdbSave(把数据以RDB文件形式保存在磁盘),rdbLoad(把RDB文件加载进内存)
- AOF(Append Only File):调用flushAppendOnlyFile函数,此函数做两件事:AOF文件的写入与保存。
- AOF写入:根据条件,将aof_buf中的缓存数据写入到AOF文件;
- AOF保存:根据条件,调用 fsync 或 fdatasync 函数,将AOF文件保存到磁盘。
3.Redis的并发竞争问题
单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,利用setnx实现锁。
4.Redis主从复制
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。
5.Redis操作时怎样保证和数据库的一致性
常规的工作流程:
- 读取数据时先去查询Redis缓存中的数据,如果缓存中有则直接读取并返回结果;如果缓存中没有就往数据库中查询数据,查询后将数据存入缓存后返回数据;
- 更新数据时先删除缓存中的数据,再更新数据库。这是由于存入缓存是一个耗时的过程,基于懒加载的思想,更新数据时先删除缓存后更新数据库,之后只有在查询相应数据时才把它加载进缓存。
高并发场景下出现的缓存不一致问题解决流程:
问题描述:在对同一数据进行更新的过程中,如果一个线程执行更新操作先删除了缓存但还未将数据的更新结果提交到数据库,此时另一个线程发送查询这一数据请求,发现缓存是空的,就会去查询数据库,但此时数据库中的数据时旧数据,但依旧会将这个旧数据读入缓存,造成了数据库的不一致。
解决方法:对于每条数据的所有操作,根据其数据的唯一标识,经过数据路由之后,存入到这条数据唯一标示所对应的jvm内部队列中,一个队列对应一个工作线程。这样,当对某条数据进行更新操作时,将更新操作放入数据所对应的队列中,这时,其它下才能恒发来的数据查询请求也会被放入队列中,由于队列的特性,更新操作一定在查询操作之前进行,从而保证了缓存与数据库的一致性。
ps:如果查询操作前有多个更新操作,则只需要存入查询操作前的最后一个更新操作,以节约内存时间开销。
问题描述:上面方法中对同一数据的所有操作都放入队列中,当对同一数据的并发操作过高时,队列后面的请求很可能得不到及时响应而导致阻塞,或者相应时间过长
解决方法:设置最大响应时间,增设服务器均摊请求
6.Redis应用场景
热点数据的缓存,限时业务的运用,计数器,排行榜,分布式锁,演延时操作,好友关系。
五.MongoDB知识点
1.MongoDB概念
MongoDB是一个文档数据库,提供好的性能,领先的非关系型数据库。采用BSON存储文档数据。BSON()是一种类json的一种二进制形式的存储格式,简称Binary JSON。相对于json多了date类型和二进制数组。
2.MongoDB支持哪些数据类型
- String
- Integer
- Double
- Boolean
- Object
- Object ID
- Arrays
- Min/Max Keys
- Datetime
- CodeRegular Expression等
3.应用场景
网站实时数据,数据缓存,大尺寸、低价值数据存储,高伸缩性场景,对象或JSON 数据存储。