大家好,这里是千寻简笔记,我是作者星辰,笔记内容整理并发布,内容有误请指出,笔记源码已开源,前往Gitee搜索《chihiro-notes》感谢您的观看。
作者各大平台直链: GitHub | Gitee | CSDN
笔记所有题目均来源于网络,仅供学习参考,如有侵权,非常抱歉,请立即联系作者删除。
网站目录格式有问题,建议下载原版阅读。
注意区分对象创建问题与类加载过程问题!
==
:对基本类型和引用类型的作用效果是不同的
==
比较的是指。==
比较的是对象的内存地址。因为只有Java
只有值传递,所以对于==
来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量
存的值是对象的地址
。
equals()
:用来比较两个对象的内容是否相等。需要注意的是equals
方法不能用于比较基本数据类型的变量。
equals
方法进行重写,则比较的是引用类型的变量所指向的地址。equals
方法,比如String、Integer等把它变成了值比较,所以一般情况下 equals
比较的是值是否相等。Java中的集合分为 value
(Conllection),key-value
(Map)两种存储结构。
value
又分为 List
、Set
、Queue
.
key-value
的为 map
其他答案:
顶层接口有:collection
之后的子接口有List,Queue, Set;
还有一个单独的Map接口
List集合是有序可重复的,支持随即访问,List接口的实现类有LinkedList,ArrayList,Vector
LinkedList底层是双向链表,不支持随即访问,但是插入与删除效率较高,ArrayList支持随机访问,但是插入与删除效率较低
Vector是线程安全的,它在一些关键方法上加了synchronized
Set集合是无序不可重复的,不支持随机访问
Map的存储方式是通过键值对的方式存储值的,键是唯一的,不可重复,value值是可重复的
Collection
:是最基本的集合接口,它提供了对集合对象进行基本操作的通用接口方法。一个 Collection
代表一组Object
,即Collection
的元素。它的直接继承接口有List
、Set
和Queue
。Conllections
:是不属于Java
的集合框架的,它是集合类的一个工具类。此类不能被实例化,服务于Java
的Collection
框架。它包含有关集合操作的静态多态方法,实现对各种集合的搜索、排序、线程安全等操作。提问:什么是缓存击穿?
缓存击穿是指某一个热点数据缓存中没有但数据库中有数据(一般是缓存时间到期)。这时由于并发用户特别多,同时读缓存没读到数据,有同时去数据库去取数据,引起数据库压力瞬间增大的,造成过大压力。
追问:缓存击穿你会怎么解决?
预先设置热门数据:在Redis
高峰访问之前,把一些热门数据提前存入Redis
里面,加大这些热门数据的key时长。
实时调整:现场监控哪些数据热门,实时调整key的过期时长。
接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些服务不可用时候,进行熔断,失败快速返回机制。
使用锁:
load db
。带成功操作返回值的操作
(比如Redis
的SETNX
)去set
一个mutex key
。load db
的操作,并回设缓存,最后删除mutex key
;load db
,当前线程睡眠一段时间再重试mutex key
;设置互斥锁:在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。(可以使用Redis分布式锁)
悲观锁:特点是总觉得正在操作的数据会被别人修改,所以自己在数据处理的过程中会将数据进行加锁。
悲观锁实现:在MySQL中使用悲观锁,需要将自动提交关闭。使用 SELECT XXX FROM XXX FOR UPDATE
这样就对查询结果加上了悲观锁(如果查询条件走了索引,则锁定的仅为查询结果集;若查询条件未走索引,则对全表加锁)
乐观锁:特点是在对数据进行操作时不会对数据或表加锁,而是在提交时判断操作过程是否有第三方对数据进行了修改,如果发现冲突,则返回错误系信息。
乐观锁实现:
version
机制是乐观锁常用的一种实现方式,一般是在数据库表中增加一列数据类型的 version
字段,查询数据时,将 version
字段读出,数据每更新一次就对version
值+1。当提交更新时,判断数据库对应的version
字段的当前值是否与第一次查询的值是否一致,若相等,则允许更新,否则认为数据过期,返回更新失败。version
。在数据库中新增时间戳字段。提交前进行比较。死锁就是资源无法被释放,举个例子:线程A占有一号锁,正在请求二号锁,且线程B占有二号锁,正在请求一号锁,A、B线程互相等待对方释放锁,进入了无限等待的状态。
死锁有四个必要条件:
如何避免死锁?破坏四个条件之一即可:
提问:索引是什么?
索引是依靠某些数据结构和算法来组织数据,最终引导用户快速检索出所需要的数据。工作方式:利用b+树
,链表
,二分查找法
,做到快速定位目标数据,快速范围查找。
索引有两个特点:
数据结构和算法
来对原始的数据
进行一些有效的组织。有效的组织
,可以引导使用者对原始数据进行快速检索
。索引的本质:
索引的数据结构:B+树
InnoDB 的数据是按数据页为单位来读写的。也就是说,当需要读取一条记录的时候,并不是将这个记录本身从磁盘读取出来,而是以页为单位,将整个页加载到内存中,一个页当中可能有很多记录,然后在内存中对页进行检索。在innodb中,每个页的大小默认是16kb。
B+树
的特征:
根节点
外,每个节点至少有[m/2]个子女,根节点
至少有两个子女。父节点
的关键字在子节点
中都存在,要么是最小值,要么是最大值,如果节点中关键字是升序的方式,父节点
的关键字是子节点的最小值
。叶子节点
。叶子节点
之外,其他节点不保存数据,只保存关键字和指针。叶子节点
包含了所有数据的关键字以及data
,叶子节点
之间用链表连接起来,可以非常方便的支持范围查找。子树的中间节点
包含了有一个k元素(B树中是k-1个元素),每个元素不保存数据,所有的数据均保存在叶子节点
上。叶子节点
中包含了全部元素的信息及指向含这些元素记录的指针,且叶子节点
本身以关键字的大小自小到大顺序连接
。中间节点
元素都同时存在于子节点
中,在子节点
元素中卫最大值或则最小值。B+树
的优势:
叶子节点
,查询性能稳定。叶子节点
形成有序链表
,便于范围查询。⭐️ 索引
分类:
分为聚集索引
和非聚集索引
。
聚集索引
每个索引有且一定会有一个聚集索引
,整个表的数据存储在聚集索引
中,MySQL
索引是B+树
结构保存在文件中,叶子节点
存储主键的值以及对应记录的数据,非叶子节点
不存储记录的数据,值存储主键的值。
当表中未指定主键时,MySQL内部自动给每条记录添加一个隐藏的rowid
字段(默认4个字节),用于rowid
构建聚集索引。
聚集索引
在MySQL中又叫主键索引。
非集聚索引
(辅助索引)
也是B+树
结构,不过有一点和聚集索引
不同,非聚集索引
叶子节点存储字段(索引字段)的值以及对应记录主键的值,其他节点只存储字段的值(索引字段)。
每个表可以有多个非聚集索引。
⭐️MySQL
中非集聚索引
分为:
索引
常见问题:
where
条件找到主键ID,利用主键ID再去查询当前这条数据的过程叫回表。ICP
,Index Condition Pushdown(ICP)
是MySQL 5.6
的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式,ICP
可以减少存储引擎访问基本表的次数以及MySQL
服务器访问存储引擎的次数。⭐️建议:
区分度高
的字段上面建立索引可以有效的使用索引,区分度太低,无法有效的利用索引,可能需要扫描所有数据页,此时和不适用索引差不多。联合索引
注意最左匹配原则:必须按照从左到右的顺序匹配,MySQL
会一直向右匹配直到遇到范围查询 >、<、between、like
就停止匹配,比如 a = 1 and b = 2 and c >3 and d = 4
如果建立 a,b,c,d
顺序的索引,d
是用不到索引的,如果建立 a,b,d,c
的索引则都可以用到,a,b,d
的顺序可以任意调整,就是 c
要放在最后,因为遇到 >
就停止匹配。索引覆盖
,可以减少回表
操作,提升效率。联合索引
,进而使用到索引下推(ICP)
,也可以减少回表的操作,提升效率。禁止
对索引字段使用函数、运算符操作,会使索引失效。%值%
会使索引无效,变为全表扫描,但是 值%
这种可以有效利用索引。优化表结构
数字型字段
。若只含数值信息的字段尽量不要设计为字符型,这回降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中的每一个字符
,而对于数字型而言只需要比较一次就够了。varchar
代替char
。可变长字段存储空间小,可以节省存储空间。索引列
存在大量重复数据时,可以把索引删除掉。比如有一列是性别,只有男、女,这样的索引是无效的。优化查询
where
子句中使用!=
或<>
操作符,否则将引擎放弃使用索引而进行全表扫扫描
。where
子句中使用or
来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
。建议使用union
替换or
。where
子句中对字段进行null
值判断,否则将导致引擎放弃使用索引而进行全表扫描
。in
和not in
也要慎用,否则会导致全表扫描
。优化嵌套查询
时可以将子查询尽量替换为多表连接查询(JOIN
)。select *
!索引优化
复合索引
,而少使用单列索引。最左前缀法则
:如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过索引中的列。order by
的字段建立索引。全表扫描
,首先考虑在where
及order by
设计的列上个建立索引。其他优化
当进行数据的insert
操作的时候,可以考虑采以下集中优化方案。
同时
对一张表插入很多行数据
时,应该尽量避免使用多个值表的insert
语句,这种方式大大缩减客户端与数据库之间的连接、关闭等消耗。使得效率比分开执行的单个insert
快。