面经准备(持续更新)

这篇博客主要涵盖了一面准备中关于网络协议、Java、数据库和操作系统的基础知识,包括HTTP请求组成部分、TCP与UDP的区别、HTTP状态码、HTTPS工作原理、线程池和Socket通信。还涉及到Java的内存管理、线程、垃圾回收、数据结构以及数据库的索引、事务和存储引擎。同时,讨论了Linux进程和线程、数据库的隔离级别、Redis缓存及其数据结构。博客内容深入浅出,是Java开发者面试的重要参考资料。
摘要由CSDN通过智能技术生成

暂不可见

一面准备

HTTP

HTTP请求组成部分
请求报文(请求行/请求头/请求数据/空行)

请求行(General) :请求方法字段、URL字段和HTTP协议版本;GET /index.html HTTP/1.1

  • 请求URL地址(Request URL) :具体要访问的接口地址,一般为域名或ip + 路径。
  • 请求方法(Request Method):GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT;

请求头 :key-value形式,User-Agent:产生请求的浏览器类型;Accpet:客户端可识别的内容类型列表;Host:主机地址;

空行 :发送回车符和换行符,表示请求头结束,通知服务器以下不再有请求头;

请求数据 :post方法中,会把数据以key-value形式发送请求。

1 GET/sample.jspHTTP/1.1
2 Accept:image/gif.image/jpeg,*/* 
3 Accept-Language:zh-cn
4 Connection:Keep-Alive
5 Host:localhost
6 User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
7 Accept-Encoding:gzip,deflate
8
9 username=jinqiao&password=1234

1为请求行,2-7为请求头,8为空行,9为数据体;

响应报文(状态行、消息报头、响应正文)
HTTP四种请求

GET:用来查询
POST:用来新增
PUT:用来修改
DELETE:用来删除

get和post的区别

  • GET 在浏览器回退时是无害的,而 POST 会再次提交请求;

  • GET请求参数是连接在URL后面的,而POST请求参数是存放在Request Body内的;

  • GET 比 POST 更不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息。

  • GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。

  • GET 请求参数会被完整保留在浏览器历史记录里,而 POST 中的参数不会被保留。

  • GET 请求在 URL 中传送的参数是有长度限制的,而 POST 么有。

  • GET 请求只能进行 url 编码,而 POST 支持多种编码方式。

  • 特别 : 大多数浏览器通常会限制url长度在2K各字节,而大多服务器最多处理64K大小的url,超过的部分直接忽略不处理。如果使用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有可能直接被忽略。

    GET和POST还有一个重大的区别,简单地说:GET产生一个TCP数据包;POST产生两个TCP数据包

    对于GET方法,浏览器会将http header和data一并发送出去,服务器响应200(返回数据);

    对于POST方法,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

http协议的content-type

一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。
常见:Content-Type: text/html; charset=utf-8

HTTP最常见的状态码:状态码大全

HTTP状态码分为五种类型:
1**:信息,服务器收到请求,需要请求者继续执行操作。
2**:成功,操作被成功接收并处理。
3**:重定向,需要进一步的操作已完成请求。
4**:客户端错误,请求包含语法错误或无法完成请求。
5**:服务器错误,服务器在处理请求的过程中发生了错误。
常见:
200 - 请求成功
301 - 永久重定向。永久移动,资源(网页等)被永久转移到其他URL
302 - 临时重定向;
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
不常见(新加):
201 (Created):成功请求并创建了新的资源,且其 URI 已经随Location 头信息返回。假如需要的资源无法及时建立的话,应当返回 ‘202 Accepted’;
403(Forbidden):表示对请求资源的访问被服务器拒绝;
502(错误网关):服务器作为网关或代理,从上游服务器收到无效响应;
503(网关超时):服务器作为网关或代理,但是没有及时从上有服务器收到请求。

Http和Https的区别:

1、https协议需要到ca申请证书;
2、http信息是明文传输协议,通过TCP完成,https则是具有安全性的ssl加密传输协议,ssl协议建立在TCP/IIP协议与各种应用层协议之间,为数据通讯提供安全支持;
3、http使用80端口,https使用443端口;
4、http连接简单无状态,https由ssl+http构建的可进行 加密传输、身份认证的网络协议;

Https

Https是在HTTP协议的基础上增加了SSL/TLS安全层。

思路:使用非对称密钥加密方式,传输对称加密密钥,保证安全性;获取到对称加密密钥后,再使用对称密钥加密方式进行通信,保证效率。

SSL协议中的流程如下:

A向B发送通信请求,B不再返回自己的公钥Public Key,而是将申请的数字签名证书返回给A。A本地维护了权威证书机构的名称和公钥,A找到对应机构的公钥,解出证书签名。A按照同样的签名规则生成自己的签名,如一至则放心使用机构公钥解出证书中的B端公钥Public Key。A生成对称加密密钥Key2,使用B端公钥Public Key加密Key2发送给B。B收到后用私钥解密得到Key2,之后两人再用Key2进行对称加密通信。

数字签名证书分发与认证:

证书分发:B向CA机构申请证书,将自己公钥加密算法RAS的公钥Public Key发送过去。CA机构手上有两个密钥CA密钥和CA公钥,CA将收到的Public Key转换为Hash值,使用CA私钥将Hash值加密,并与B的公钥Public Key绑定一起,这就是数字签名证书。所以数字签名证书就是服务端B公钥 + 经CA私钥加密的公钥Hash值

证书验证:A收到数字签名证书后,使用CA公钥解密加密值,并与配套的服务端公钥转化的Hash值比对,比对成功则认证成功,使用此公钥即可。

一次完整HTTP的网络请求发生了什么
  • 输入url到网页显示经历了什么
    在这里插入图片描述
    一次完整的HTTP请求过程是怎么样的呢?
    1.浏览器进行DNS域名解析,得到对应的IP地址;
    2.根据这个IP,找到对应的服务器建立连接(三次握手);
    3.建立TCP连接后发起HTTP请求(一次完整的http请求报文);
    4.服务器响应HTTP请求,浏览器代码得到html代码
    5.浏览器解析html代码,并请求html代码中的资源(如js、css、图片等);
    6.浏览器对页面进行渲染呈现给用户;
    7.服务器关闭TCP连接(四次握手);
一个TCP连接可以发送多少个HTTP请求

面试题:每发送一个http请求就要建立一个tcp连接吗(非持久连接/持久连接)

Header中Connection属性决定连接是否持久,HTTP/1.0中Connection默认时close,即每次请求都会重新建立和断开TCP连接,在HTTP/1.1中Connection默认时keep-alive,即连接可以复用,不用每次都重新建立和断开TCP连接。一般情况复用的TCP连接在等待设置的超时时间之后还没有被任何连接使用的话,TCP连接就会主动断开。

一个TCP连接如果维持连接,可以发送多个HTTP请求。
一个TCP连接中HTTP请求可以一起发送吗?比如一起发送三个请求,再三个一起接受?

HTTP/1.1默认单个TCP连接再同一时刻只能处理一个请求,即两个请求的生命周期不能重叠,任意两个HTTP请求从开始到结束的时间在同一个TCP连接里不能重叠。

但是规范中规定了Pipelining来解决这个问题,一个支持持久连接的客户端开一在一个连接中发送多个请求(不需要等待任意请求的响应),收到请求的服务器必须按照请求收到的顺序发送响应,因为浏览器没有办法根据响应来判断响应对应于那个请求。

HTTP/2中,通过连接复用Multiplexing进行多个HTTP请求并行发送。HTTP2.0中,提出了帧frame和流stream的概念,帧时最小的数据单位,每个帧会标识出该帧属于哪个流,流是由多个帧组成的数据流。

多路复用,就是在一个TCP连接中可以存在多条流,换句话说,可以发送多个请求,对端可以通过帧的标识知道属于哪个请求。

浏览器对同一Host建立TCP连接到数量有没有限制

Chrome最多允许对同一Host建立六个TCP连接。

浏览器需要加载十几张图片的网页时,图片以什么方式、什么顺序、建立了多少连接,使用什么协议被下载下来呢。

如果图片都是HTTPS连接并且在同一域名下,浏览器在SSL握手之后会和服务器商量能不能使用HTTP2,能的话使用多路复用Multiplexing功能,在一个TCP连接上进行多路传输。但未必在这个域名下的资源都会使用一个TCP连接去获取。

如果发现用不了HTTP2,浏览器就会在一个HOST上建立多个TCP连接,连接的最大限制取决浏览器的限制,连接在空闲时会被浏览器用来发送新的请求,如果所有连接都被占用,其他请求只能等待。


HTTP无状态

HTTP是一种无状态协议,即服务器不保留与客户交易时的任何状态。上一次的请求对下一次的请求没有任何影响,服务端也不会对客户端上一次请求进行任何的记录

保持HTTP状态的技术,一个是Cookie,另一个是Session。

参考
HTTP协议为什么是无状态的?如何让HTTP“有状态”

Cookie

Cookie是一小段文本信息(Key-Value),是客户端的存储空间,由浏览器维持。Cookie由服务器生成并发送给客户端,根据服务器的响应报文中的字段Set-Cookie,客户端保存Cookie,下次客户端再向服务器发送请求时,自动在请求报文中加入Cookie值。服务端发现客户端发送的Cookie后,会检查从哪一个客户端发来的请求并对比服务器记录,得到之前的状态信息,就像填完信息办理的银行卡。

Session

Session是另一种记录客户状态的机制,Session保存在服务器上。Session需要使用Cookie作为识别标志,因为HTTP协议是无状态的,无法判断是否为统一用户。Session需要依靠名为sid(SessionId)的Cookie识别是否为同一用户。就像服务器建立的一份客户档案,客户来访只需查询档案即可。

Session如何判断是否是同一会话
服务器第一次收到请求时,开辟一块Session空间(创建Session对象),同时生成SessionId,通过响应头Set-Cookie:JSESSIONID=XXX命令,向客户端发送响应设置Cookie,客户端收到响应后,在本机客户端设置JSESSIONID=XXX的Cookie信息。接下来客户端每次向服务器发送请求时,请求头都会带上该Cookie信息。服务器通过请求中的Cookie信息得到SessionId

Cookie功能被禁用,Session也可以通过URL重写进行会话跟踪,每次HTTP交互URL后会被附加sid=XXX的参数,用来识别用户。
在这里插入图片描述

URI 和 URL

URI(Uniform Resource Identifier)统一资源标识符。是一种标识,用来区别于其他网络资源的标识。URI不是固定的,不同的参照角度看到的URI不同,是相对地址。
在这里插入图片描述

URL (Uniform Resource Locator) 统一资源定位符。浏览器的一串完整的地址就是URL。

URI是URL的父级,URL相当于继承了URI,但比URI更加详细。

参考
URI和URL的区别比较与理解
搞什么啊? URI 和 URL 到现在还不清楚?

tcp和udp

tcp和udp区别:

tcp面向连接,udp是无连接;
tcp是可靠性传输,udp是不可靠传输(tcp可靠性通过检验、序号、确认、重传保证);
tcp面向字节流,udp面向数据包;
tcp保证数据的正确性、数据顺序,udp不保证;
tcp首部为20字节,udp首部为8字节;

  • tcp建立连接为什么要三次握手:
    原因:避免重复链接, 防止旧的滞留请求引起连接混乱。
    The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

在这里插入图片描述

“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

tcp断开连接为什么要四次握手:

因为TCP是一个全双工通信。服务端接收到FIN请求后通常要等待自己的数据发送完成后再发送FIN请求。
在这里插入图片描述
1、当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据口(当然确认信号还是可以发),就会发FIN给主机B。
2、主机B收到A发送的FIN,表示收到了,就会发送ACK回复。
3、但这是B可能还在发送数据,没有想要关闭数据口的意思,所以FIN与ACK不是同时发送的,而是等到B数据发送完了,才会发送FIN给主机A。
4、A收到B发来的FIN,知道B的数据也发送完了,回复ACK, A等待2MSL以后,没有收到B传来的任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接了。

  • Client为什么最后还要等待2MSL,从TIME_WAIT到CLOSE?
    MSL(Maximum Segment Lifetime)最大片段存活时间,2MSL就是一个发送和一个回复所需的最大时间。
    在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段,所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态,Client会设置一个计时器,等待2MSL时间,如果改时间内再次接受到FIN,那么Client会重发ACK并再次等待2MSL。若直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

二面新加

SYN、ACK、seq都表示什么?

TCP有六种标志位:
1. SYN(synchronous同步的)建立联机;
2. ACK(acknowledgement)确认;
3. PSH(push)传送;
4. FIN(finish)结束;
5. RST(reset)重置;
6. URG(urgent)紧急;

**seq(Sequence number)顺序号码**:表示的是发送方这边,这个packet的数据部分的第一位应该在整个data stream中所在的位置。(注意这里使用的是“应该”。因为对于没有数据的传输,如ACK,虽然它有一个seq,但是这次传输在整个data stream中是不占位置的。所以下一个实际有数据的传输,会依旧从上一次发送ACK的数据包的seq开始)
**ack(Acknowledge number)确认号码**:表示的是接收方期望下一次sequence number是多少。
什么是套接字(Socket)通信?

套接字(socket)由一个ip地址和一个端口号组成。
网络通信每对进程都需要使用一对套接字进行通信,每个进程各有一个socket。(应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程并发服务的问题,多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据,Socket则是为了区别不同的应用程序进程和连接。)
在这里插入图片描述1、服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket
2、服务器为socket绑定ip地址和端口号
3、服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开
4、客户端创建socket
5、客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket
6、服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直到客户端返回连接信息后才返回,开始接收下一个客户端连接请求
7、客户端连接成功,向服务器发送连接状态信息
8、服务器accept方法返回,连接成功
9、客户端向socket写入信息
10、服务器读取信息
11、客户端关闭
12、服务器端关闭

ARP协议

ARP(Address Resolution Protocol)地址解析协议,工作在网络层,为IP地址到对应的MAC地址之间提供动态映射。
在这里插入图片描述

ARP协议中解析的IP地址一定是在本地网络中并进行直接交付,先查询ARP高速缓存表是否已有记录,再广播发送ARP请求到以太网上的每个主机,广播是在数据链路层上执行,MAC地址位FF-FF-FF。ARP请求中包含目的主机的IP地址,目的主机收到报文后回复ARP应答包含目的IP地址和MAC地址,源主机收到后记录在ARP高速缓存表中。

这里有四种典型情况:

1.发送方H1发送IP数据报到同一个网络上的另一台主机H2:H1发送ARP请求分组在此网络广播,找到目的主机H2的硬件地址。

2.发送方H1发送IP数据到另一个网络上的主机H3:H1发送ARP请求分组在此网络广播,找到此网络的路由器R1硬件地址。剩下的工作由路由器来完成,路由器完成的事情为下面的3,4。

3.发送方是路由器R1,要将IP数据包转发至与R1直连网络2上的主机H3:R1发送ARP请求分组在网络2上广播,找到主机H3的硬件地址。

4.发送方式路由器R1,要将IP数据包转发至不与R1直连网络3上的主机H4:R1发送ARP请求分组在直连网络2上广播,找到网络2上另一个路由器R2的硬件地址,剩下的工作由R2完成。

在这里插入图片描述

网络链路上传输的帧最终是按照硬件地址寻找目的主机,但还要使用抽象的IP地址,为什么不直接使用硬件地址通信呢?这样似乎可以免除ARP

由于全世界存在各式各样的网络,他们使用不同的硬件地址,要是这些异构网络能够互相通信就必须进行非常复杂的硬件地址转换工作,由用户或用户主机完成这项工作几乎不可能。IP编制将这个复杂问题解决了,连接到互联网的主机只需各自拥有一个唯一的IP地址,它们之间的通信就像连接在同一个网络那样简单,而调用ARP的复杂过程都是由计算机软件自动执行的,用户是看不见这种调用过程的。

交换机与ARP的关系

交换机工作在数据链路层,根据MAC地址进行转发,并将MAC地址与对应端口记录在内部的地址表中。

在局域网内的计算机首次通信时,因为需要MAC地址才能通信,而首次通信时不知道对方的MAC地址,需要通过ARP来获取。ARP请求包通过交换设备中转,分发给除了发送端所有主机。

DNS协议

DNS(Domain Name System)将主机域名转换为ip地址。工作在应用层使用UDP协议。有两种查询方式:(1)递归查询、(2)递归和迭代结合查询(主机向本地域名服务器递归查询,主机域名服务器向根域名服务器采用迭代查询),常用递归迭代结合查询。
在这里插入图片描述

DNS查询详情

查询y.abc.com的IP地址步骤:

  1. 客户向本地域名服务器以发送DNS请求;
  2. 本地域名服务器收到请求后查询本地缓存,若无记录则以DNS客户身份向根域名服务器发出解析请求;
  3. 根域名服务器判断该域名属于.com域,将对应的顶级域名服务器dns.com的IP地址返回给本地域名服务器;
  4. 本地域名服务器向dns.com发送请求;
  5. 顶级域名服务器dns.com判断该域名属于abc.com域,将对应授权域名服务器dns.abc.com的IP地址返回本地域名服务器;
  6. 本地域名服务器下向授权域名服务器发送查询dns.abc.com发送请求报文;
  7. 授权域名服务器dns.abc.com收到请求后,将查询结果返回给本地域名服务器;
  8. 本地域名服务器将查询结果保存到本地缓存,同时返回给客户机。
  • ISO的OSI七层网络结构与TCP/IP四层结构
    在这里插入图片描述

2. linux查看进程 ps (Processes Status)


ps -xx:

  • -a显示当前终端运行的所有的进程信息
  • -u以用户的信息显示进程
  • -x显示后台运行进程的参数
#ps -aux 查看所有进程
ps -aux|grep mysql
# | 在Linux这个叫做管道符 A|B
# grep 用于查找文件里符合条件的字符串

ps -ef:可以查看到父进程信息,也可以用pstree图形化查看

pstree -pu
# -p 显示父id
# -u 显示用户组

杀死进程kill

kill -9 pid
# -9强制杀死进程

3.数据库

按功能区分数据库的索引

索引是用于排序,便于查找数据的数据结构。

  • 唯一索引:唯一、不重复的索引;
  • 主键索引:唯一不重复,且不为空的索引;
  • 普通索引:可以重复且空的索引;
  • 组合索引:基于多个字段而创建的索引称;
    组合索引遵从最左前缀原则
  • (全文索引)

索引采用的数据结构为B+树。

按存储方式分聚簇索引和非聚簇索引

参考:添加链接描述

1,聚簇索引 :叶子节点就是数据节点,索引与数据存放在一起,找到了索引也就找到了数据。一个表只能有一个聚簇索引。

2.非聚簇索引:B+树叶子节点储存的是主键的值。二级索 / 辅助索引属于非聚簇索引。

Innodb使用的聚簇索引,MyISAM使用的非聚簇索引:

当我们基于 InnoDB 引擎创建一张表的时候,都会创建一个聚集索引,每张表都有唯一的聚集索引:

如果这张表定义了主键索引,那么这个主键索引就作为聚集索引。
如果这张表没有定义主键索引,那么该表的第一个唯一非空索引作为聚集索引。

如果这张表也没有唯一非空索引,那么 InnoDB 内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个 6 个字节的列,该列的值会随着数据的插入自增。

聚簇索引是索引与数据的结合,决定了表的物理排列顺序,一个表只能有一个物理排列顺序。若果有多个聚簇索引,会发生数据的冗余。

非聚簇索引的索引顺序与数据的物理顺序无关,一个表可以有多个非聚簇索引。

主键索引和普通索引有什么区别

主键索引属于聚簇索引,叶子节点存放整行数据,找到了索引也就找到了数据;

普通索引是二级索引/辅助索引,属于非聚簇索引,叶子节点存放的是主键的值。查询条件为普通索引,需要扫描两次B+数,第一次通过普通索引定位主键的值,再通过聚主键值查找行记录数据。

根据主键索引查询,只需要搜索ID这颗B+树。
根据非主键索引查询,需要先搜索k索引树,找到叶子节点中对应的主键,再到ID索引树搜索一次,这个过程叫回表。非主键索引的查询需要多扫描一颗索引树,查询相对更低。
在这里插入图片描述
在这里插入图片描述

组合索引和普通索引的区别

1.减少开销
一个联合索引(co1, col2, col3),实际相当于建立了(col1), (col1, col2), (col1, col2, col3) 三个索引。不然每多一个索引,都会增加写操作的开销和磁盘空间的开销。

2.覆盖索引
对于联合索引(col1,col2, col3)如果有sql:

select col1, col2, col3 from test where col1 = 1 and col2 = 2

那么MySQL可以直接通过遍历索引获取数据,无需回表,减少了很多随机io操作。
在这里插入图片描述
3.索引列越多,通过索引筛选出的数据越少,效率越高
上述的查询语句,假设每个条件可以筛出10%的数据,如只有单列索引col1,通过col1晒出10%的数据后,再回表从这10%的数据中找到col2 = 2 and col3 = 3的数据。但是组合索引,可以通过索引直接筛出10% *10% *10%的数据,效率提升明显!

什么是索引下推

MySQL5.6以后版本以后推出的优化,索引下推是为了减少不必要的回表操作,对于查找出来的数据,先过滤掉不符合条件的,其余的再去主键索引树上查找。

联合索引(name, sex),进行操作:

select * from user where name like '王%' and sex = 1

name可以走索引,但是sex无法走索引,如果妹有索引下推就需要对通过name找到的数据分别进行回表查找。
在这里插入图片描述
通过索引下推,存储引擎会先对查找出来的数据进行条件过滤,剩余的再进行回表进行。
在这里插入图片描述

设计索引要注意什么?

1.非空字段,应该指定列为NOT NULL。 Mysql中,含有空值的列很难进行查询优化,用0、特殊值或空串代替空值。

2.唯一索引,唯一属性的列上建立唯一索引。

2.不要在更新比较频繁的列上建立索引,会降低更新时效率,因为每次更新都要对索引的存储进行维护。区分度不高(比如只有一个状态0/1的标识)也不要建立索引。

**3.如果单列和组合索引都可以实现,建议使用组合索引。**因为一个单列索引就会建立一个B+树存储结构,太多单列索引会占用过多的空间。

4.使用组合索引要注意最左前缀原则,避免索引失效,区分度高的列放在最左边,组合数量不宜过多。

5.索引的长度,有时并不需要将字段列中所有值都存储在索引中,可以计算索引的区分度,控制索引的长度,减少索引占用的空间,使得一次IO读取更多的索引到内存中,提高索引的查询效率。

索引优化案例

分页查询优化

业务要根据时间范围查询交易记录,接口原始的SQL如下:

select  * from trade_info where status = 0 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59' order by id desc limit 102120, 20;

表中有索引idx_status_create_time(status, create_time)。对于分页limit m, n来说,越往后翻页越慢,也就是m越大越慢,因为定位m位置需要扫描的数据越来越多,导致IO开销比较大。可以利用辅助索引的覆盖扫描进行优化,通过索引查询id不需要回表,再通过id和原表进行关联。

select * from trade_info a, 
(select id from trade_info where status = 0 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59' order by id desc limit 102120, 20) as b
where a.id = b.id
最左前缀原则

最左前缀匹配原则,对于索引中的字段,mysql会一直向右匹配直到遇到范围查询(>, <, betwwen, like, !=)就停止匹配。

  1. =, in条件的索引可以任意顺序,查询优化器会帮助自动形成可识别的形式。

1.范围会结束索引(范围会走),后面的字段会停止索引。
where age > 20 and name = '小张'age会走索引但是name不会走索引。

2.like %在前面不走索引,%在后面走索引
A:select * from student where 'name' like '%王' 不走
B:select * from student where 'name' like '%小'

3.!=不走索引

4.对索引列进行计算不走索引
A:select * from student where age = 10+8
B:select * from student where age + 8 = 18 不走

5.对索引列用函数不走索引
A:select * from student where concat('name','哈') ='王哈哈'; B:select * from student where name = concat('王哈','哈');

最左前缀原则的B+树结构

索引树,存储了联合索引中的所有索引列,存储引擎会首先根据第一个索引列排序,第一个索引列相等再根据第二个索引列排序,以此类推。
在这里插入图片描述

select * from T1 where b = 12 and c = 14 and d = 3

存储引擎首先从根节点开始查找,根节点一般一般常驻内存。第一个索引节点的第一个索引列为(1,1,4),首先判断b索引的值, 1<12<56,于时从这俩索引的中间读到下一个节点的磁盘文件地址,从磁盘Load这个节点,伴随一次IO,然后在内存中去继续查找…直到找到叶子节点,伴随一次磁盘IO,在叶子节点中比较数据,找到符合的索引列,找到该索引下的主键值,再从主键索引树上找到最终数据。

B+树是什么

链接:什么是B+树
B+树的特征:

1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。

2.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

3.所有的叶子结点中包含了全部元素的信息及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

补充:数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。非聚集索引(Unclustered Index)中,叶子节点带有指向卫星数据的指针。
在这里插入图片描述

B+树的优势:

1.单一节点存储更多的元素(中间节点只做索引没有卫星数据),数据量相同b+树比b-树更加矮胖,使得查询的IO次数更少。

2.所有查询都要查找到叶子节点,查询性能稳定。

3.所有叶子节点形成有序链表,便于范围查询(B-树的范围查询只能繁琐的中序遍历)。

Mysql引擎
  • Innodb引擎
  • MyISAM引擎 /my-z[ei]m/

MyISAM引擎

MyISAM是MySQL默认的引擎,但是他没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率会低一些。不过和InnoDB不同,MyISAM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时,只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyISAM也是很好的选择。

Innodb引擎

InnoDB引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持FULL TEXT类型的索引,而且他没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。

当需要使用数据库事务时,该引擎是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb会提升效率,但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。

使用场景
大尺寸的数据集倾向于选择InnoDB引擎,因为它支持事务处理和故障恢复。数据库的大小决定了故障恢复的时间长短,InnoDB可以利用事务日志进行数据恢复,这会比较块。主键查询在InnoDB引擎下也会相当快不过需要注意的是如果逐渐太长也会导致性能问题。大批的INSERT语句(在每个INSERT语句中写入多行,批量插入)在MyISAM下会快一些,但是UPDATE语句在InnoDB下则会更快,尤其是在并发量大的时候。

数据库事务Datebase Transaction

数据库事务是数据库并发控制的基本单元,一个逻辑工作单元必须由四个属性,称为ACID(原子性、一致性、隔离性和持久性)属性。

数据库事务四大特性

1. 原子性(Atomicity): 事务包含的所有数据库操作要么全部成功,要不全部失败回滚
2. 一致性(Consistency): 个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
3. 隔离性(Isolation): 一个事务未提交的业务结果是否对于其它事务可见,并发事务不会相互干扰。(级别一般有:read_uncommitted,read_committed,Repeatable read(默认),Serializable串行化访问)
4. 持久性(Durability): 一个事务一旦被提交了,那么对数据库中数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

数据库事务的隔离级别
事务隔离级别有四个,由低到高依次为读未提交(Read uncommitted)、读已提交(Read committed)、可重复读(Repeatable read)、串行化(Serializable),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

在这里插入图片描述

  1. 脏读(Dirty Reads):事务A执行过程中对数据资源进行了修改,事务B读取了事务A修改后的数据;由于某些原因,事务A并没有完成提交,发生了回滚(RollBack)操作,则事务B读取到的数据为脏数据。在这里插入图片描述

  2. 不可重复读(Non-Repeatable Reads):事务B读取了两次数据,在两次读取的过程中事务A修改了数据,导致事务B在这两次读取出来的数据不一致。

    这种在同一事务中,前后两次读取的数据不一致的现象就是不可重复读(Nonrepeateable Read)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值