本文主要是介绍Minimax-秋招正式批-面经(other),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1. 谈谈对聚簇索引的理解
聚簇索引
- InnoDB通过主键聚集数据,如果没有定义主键,InnoDB会选择非空的唯一索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引
- 聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是该行的行记录数据,也将聚簇索引的叶子节点称为数据页。这个特性决定了索引组织表中数据也是索引的一部分,每张表只能拥有一个聚簇索引
非聚簇索引
- 在聚集索引之上创建的索引叫做辅助索引
- 辅助索引访问数据总是需要二次查找,第一次找到主键值,第二次根据主键值找到行数据
- 辅助索引叶子节点存储的不再是行的物理位置,而是主键值。
- 通过辅助索引首先找到的是主键值,再通过主键值找到数据行的数据页,再通过数据页中的Page Directory找到数据行。
聚簇索引⼀个表只能有⼀个,而非聚簇索引⼀个表可以存在多个。聚簇索引存储记录是物理上连续存在,而非聚簇索引是逻辑上的连续,物理存储并不连续。
聚簇索引的优势
- 数据访问更快:
- 由于行数据和叶子节点存储在一起,同一页中会有多条数据,访问同一数据的不同行记录时,已经把页加载到了Buffer中,再次访问的时候,会在内存中完成访问,不必访问磁盘
- 这样由于主键和行数据时一起被载入磁盘的,找到叶子节点就可以立即将行数据返回了,如果按照主键ID来组织数据,获得数据更快
- 聚簇索引对主键的排序查找和范围查找速度非常快
- 聚簇索引适合用在排序的场合,非聚簇索引不适合
- 取出一定范围数据的时候,使用用聚簇索引
聚簇索引的缺点
- 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID作为主键
- 主键的值是顺序的,所以InnoDB会将每一条记录都存储在上一条记录的后面。
- 当达到页的最大填充因子(InnoDB 默认的最大填充因子是页大小的 15/16,留出部分空间用于以后修改)下一条记录就会被写入到新的页中。
- 一旦数据按照这种顺序的方式被加载,主键也就会近乎与被顺序的记录填满(二级索引页可能是不一样的)
- 维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(page split)的时候。因此,对于InnoDB表,我们一般定义主键不可更新;另外,建议在大量插入新行后,选在负载较低的时间段,通过OPTIMIZE TABLE优化表,因为必须被移动的行数据可能造成碎片。使用独享表空间可以弱化碎片
- 如果主键比较大的时候,那辅助索引将会变得更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用更多的物理空间
2. mysql为什么要求id递增?
- 索引性能:聚簇索引的数据的物理存放顺序与索引顺序是一致的,只要索引是相邻的,那么对应的数据一定也是相邻的存储在物理磁盘上的。如果主键不是自增ID,那么当插入数据时会进行频繁的页分裂或移动数据,当然也有一些措施来减少这些操作,但是却无法彻底避免。但是,如果是自增的,那就简单了,它只需要一页一页的写,索引结构相对紧凑,磁盘碎片少,效率也高。
- 唯一性保证:自增主键保证了每一行的唯一性。每次插入新行时,数据库会自动为主键生成一个唯一的值,无需开发人员手动指定。这消除了开发人员处理唯一性约束的复杂性和潜在的错误。此外,自增主键还可以简化表之间的关联关系,作为外键的引用。
- 索引大小和查询性能:自增主键的值通常较小,只需要占用很少的存储空间。相比于使用其他类型的列作为主键,自增主键可以减小索引的大小,提高查询性能。较小的索引大小也可以减少内存的消耗,更好地适应于内存缓存。
- 数据可维护性:自增主键提供了一种简单且可维护的方式来标识和引用表中的每一行。开发人员可以轻松地使用主键进行数据的更新、删除和查询操作,而不需要关心主键值的生成和管理。
3. mysql回表是什么?
Mysql回表指的是在InnoDB存储引擎下,二级索引查询到的索引列,如果需要查找所有列的数据,则需要到主键索引里面去取出数据。这个过程就称为回表。因为行的数据都是存在主键B+tree的叶子节点里面,二级索引的B+树叶子节点都是存放的(索引列,主键)。
例如:有一张用户表 id(主键), username (二级索引),age
id是主键索引 username是二级索引,当我们通过二级索引查询返回记录时,例如:
select * from t where username = "bobo";
① 通过二级索引找到 username为bobo的主键id
② 在通过主键id去主键索引B+tree找到行记录
4. MySQL为什么默认引擎是InnoDB?
- 支持事务:InnoDB 是一个支持事务的存储引擎。事务是一组数据库操作的原子性执行,可以保证操作的一致性和完整性。
- 并发控制:InnoDB 支持行级锁定,在高并发环境下可以最大程度地减少锁冲突,提高并发性能。相比之下,MySQL 的另一个存储引擎 MyISAM 只支持表级锁定,并发性能较低。
- 外键约束:InnoDB 支持外键约束,可以保证数据的完整性。外键用于建立表与表之间的连接,通过外键约束可以实现数据之间的关联和参照完整性。
- 崩溃恢复:InnoDB 具有自动崩溃恢复的能力。即使在发生意外故障或系统崩溃时,InnoDB 引擎也能够自动进行崩溃恢复,保障数据的一致性。
- 支持热备份:InnoDB 支持在线热备份,可以在不停止数据库服务的情况下进行备份操作。这对于需要实时运行且对数据可用性要求高的应用程序非常重要。
5. mysql为什么不用uuid做主键?
UUID:UUID 是指Universally Unique Identifier(通用唯一识别码),UUID 的目的是让分布式系统中的所有元素都能有唯一的识别信息。如此一来,每个人都可以创建不与其他人冲突的 UUID,就不需考虑数据库创建时的名称重复问题。
1. 索引效率:
- 无序性:UUID是随机的,没有规律可言,因此InnoDB无法总是将新行插入到索引的最后。这导致InnoDB需要为新行寻找新的合适位置并分配新的空间,增加了额外的操作。
- 页分裂:由于写入是乱序的,InnoDB需要频繁进行页分裂操作以为新行分配空间。页分裂不仅移动了大量的数据,还降低了索引的紧凑性,增加了碎片的产生。
- 随机IO:由于UUID的随机性,写入的目标页可能尚未加载到缓存中,或者已经被刷新到磁盘并从缓存中移除。这导致InnoDB在插入之前不得不先从磁盘读取目标页到内存中,增加了随机IO的次数。
2. 性能影响:
- 插入效率:由于上述的随机IO和页分裂问题,UUID作为主键的表在插入操作上的性能通常低于自增ID作为主键的表。
- 优化需求:在将随机值(如UUID)载入到聚簇索引后,有时需要进行OPTIMIZE TABLE操作以重建表并优化页的填充。这将消耗额外的时间和资源。
自增id:自增的主键的值是顺序的,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子时候(innodb默认的最大填充因子是页大小的15/16,会留出1/16的空间留作以后修改)
1. 索引效率:
- 顺序性:自增ID是顺序的,InnoDB能够高效地将新记录插入到索引的末尾,减少了页分裂和碎片的产生。这意味着数据在物理存储上也是连续的,从而提高了查询和插入的效率。
- 填充率:由于数据是按照顺序插入的,InnoDB能够近乎于顺序地填满每个索引页,提高了页面的最大填充率,减少了空间的浪费。
- 定位与寻址:新插入的行一定会在原有的最大数据行下一行,MySQL定位和寻址很快,不需要为计算新行的位置而做出额外的消耗。
2. 性能影响:
- 锁争用:在高并发的负载下,InnoDB在按主键进行插入时可能会造成锁争用,因为所有的插入都发生在主键的上界,这可能导致间隙锁竞争。
- 泄露信息:自增ID容易被外部爬取,从而暴露业务增长信息,可能对企业的经营情况造成潜在风险。
总结:
- 自增ID:适用于大多数需要高效查询和插入操作的场景。它简单易用,索引效率高,但需要注意在高并发下的锁争用问题和信息泄露风险。
- UUID:适用于需要全局唯一标识符的场景,特别是在分布式系统中。然而,其随机性导致了较低的索引效率和较高的插入成本。
6. websocket和http区别
websocket知识点总结_防火墙 websocket-CSDN博客
相同点
- 都是基于TCP协议,都是可靠性传输协议
- 都是应用层协议
不同点
HTTP
- 类型: 请求-响应式的无状态协议,半双工通信,同一时刻只能一个方向上有动作
- 通信方式: 单向传输,从浏览器到服务器
- 连接持久性: 虽能支持通过 Keep-Alive 持久化连接,但有超时时间,其实仍需多次握手
- 服务器推送:是一种客户端主动发起请求的协议,服务器只能在收到请求后才能返回响应
-
通信效率:由于HTTP协议每次通信都需要经过完整的请求-响应过程,包括建立连接、发送请求、服务器处理请求、发送响应等步骤,因此在频繁通信的场景下,HTTP的开销较大
WebSocket:为了解决HTTP双向通信和服务端主动推送的不足
- 类型:全双工通信协议。
- 通信方式:浏览器和服务端可以双向发送和接受信息
- 连接持久性: 在一个 TCP 连接上持续通信,减少了连接和断开的次数。
- 服务器推送:支持服务器主动推送数据给客户端,服务器可以随时向客户端发送数据,实现实时通信
- 通信效率:在建立连接后只需要发送少量的头部信息,然后就可以直接进行数据传输,通信效率较高
websocket只需要服务器和浏览器通过HTTP协议进行一个握手的动作,然后单独建立一条TCP的通信通道就可以进行数据的传送了。整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求,减少了解析请求信息的效率问题。全双工双向通信,服务端可以主动推送数据给客户端。WS连接建立之后,数据的传输使用帧来传递,不再需要Request消息,数据帧有序。
扩展:什么是HTTP无状态?
HTTP无状态协议,是指协议对于交互性场景没有记忆能力。
在点击一个纯的html网页,请求获取服务器的html文件资源时,每次http请求都会返回同样的信息,因为这个是没有交互的,每一次的请求都是相互独立的。第一个请求和第二个请求也没有先后顺序,返回处理哪个,结果都是同样的资源页面,因为这种场景是无交互的,无论是什么人请求这个地址,服务器都是返回那个相同的响应。
在无交互场景中上面那样,当然也不会有太大的问题。但是对于涉及到动态交互的场景,就显得很尴尬了,何为交互?有来又有往,对于一模一样的两个接口,不同的人在请求第二个接口时可能会基于请求第一个接口的结果而有所不同。
现在我们来想一个复杂的场景,如在购物网站上买一个书包,流程如下:
- 输入账号密码登陆 /login 用户信息
- 选择一款你喜欢的书包加入到购物车中 /cart 用户信息,产品信息
- 购买支付 /pay 用户信息,商品信息,金额信息
所谓的登录只是验证你是否是一个合法用户,若是合法则跳转到信息的页面,不合法则告知用户名密码错误。但是我们在第一步给服务器发完/login接口后,服务器就忘记了。。。忘记了你这个人,到底有没有经过认证。所以在添加商品时/cart 你还是需要将你的账号密码和商品信息一起提交给 addCart接口,再让服务器做验证。第三步同理。
7. webSocket与socket的区别
socket为套接字,是计算机之间进行通信的一种约定或一种方式,封装了TCP/IP协议,是一个接口。socket起源Unix,可以用“打开open -> 读写write/read -> 关闭close” 模式来操作。Socket代表了在操作系统中传输数据的两方,它并不是什么协议,只是它不再基于网络协议,而是操作系统本身的文件系统
区别:
- socket是传输控制层的接口,用户可以通过socket来操作系统底层TCP/IP协议通信。
- webSocket是一个完整的应用层协议
- WebSocket 更易用,因为它是一个完整的应用层协议,包含一套标准的API,使用起来相对简单。Socket 更灵活,因为它是一个门面模式,把复杂的TCP/IP协议族隐藏在Socket接口后面,使得用户可以根据自己的需求灵活地使用TCP或UDP来传输数据。
- 两者都能做即时通讯
8. http和rpc的区别
RPC(即Remote Procedure Call,远程过程调用)和HTTP(HyperText Transfer Protocol,超文本传输协议)他们最本质的区别,就是RPC主要工作在TCP协议之上,而HTTP服务主要是工作在HTTP协议之上,我们都知道HTTP协议是在传输层协议TCP之上的,所以效率来看的话,RPC当然是要更胜一筹。
- RPC是一种进程内通信机制,HTTP是一种网络应用协议。
- RPC使用TCP或UDP,HTTP只使用TCP。
- RPC使用自定义的数据格式(比如XML、JSON等),HTTP使用标准MIME类型(如HTML、XML、JSON、图片等多种格式)。
- RPC是持续连接,HTTP是短连接。
- RPC用于内部集成,HTTP用于Web应用。
RPC架构:
客户端(Client),服务的调用方。
服务端(Server),真正的服务提供者。
客户端存根 ( Client Stub),存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
服务端存根 (Server Stub),接收客户端发送过来的消息,将消息解包,并调用本地的方法。
9. 为什么 InnoDB 底层使用 B+ 树
这篇关于Minimax-秋招正式批-面经(other)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!