2021年阿里Java高级面试题及答案,MySQL8

MySQL因为没有实现hashjoin而受到批评。最新的8.0.18版本带来了这一功能,令人欣慰。有时候我想知道为什么MySQL不支持hashjoin?我认为这可能是因为MySQL主要用于简单的OLTP场景,而且它广泛应用于Internet应用程序中,所以需求并不那么迫切。另一方面,这可能是因为以前完全依赖社区。毕竟MySQL的进化速度是有限的。甲骨文收购mysql后,mysql发布的演进速度明显加快。

  • 源点:提供流的节点(入度为0),类比成为一个无限放水的水厂

  • 汇点:接受流的节点(出度为0),类比成为一个无限收水的小区

  • 弧:类比为水管

  • 弧的容量:类比为水管的容量;用函数c(x,y)c(x,y)表示弧(x,y)(x,y)的容量

  • 弧的流量:类比为当前在水管中水的量;用函数f(x,y)f(x,y)表示弧(x,y)(x,y)的流量

  • 弧的残量:即容量-流量

  • 容量网络:对于一个网络流模型,每一条弧都给出了容量,则构成一个容量网络。

  • 流量网络:对于一个网络流模型,每一条弧都给出了流量,则构成一个流量网络。

  • 残量网络:对于一个网络流模型,每一条弧都给出了残量,则构成一个残量网络。最初的残量网络就是容量网络。

hashjoin本身的算法实现并不复杂。要说它很复杂,可能是优化器选择执行计划时,是否选择hashjoin,选择外观,内部表可能更复杂。无论如何,现在使用hashjoin,优化器在选择join算法时还有另一个选择。MySQL基于实用主义。我相信这个增强也回答了一些问题。有些职能并非无能,而是有优先权。

在8.0.18之前,MySQL只支持nestlopjoin算法。最简单的是简单的nestloop连接。MySQL对该算法进行了一些优化,包括块嵌套循环连接、索引嵌套循环连接和批密钥访问。通过这些优化,可以在一定程度上缓解hashjoin的紧迫性。接下来,我们将用一个单独的章节来讨论MySQL的这些连接优化。接下来,我们将讨论hashjoin。

Hash Join算法

Nestloopjoin algorithm is simply a double loop, which traverses the surface (drive table), for each row of records on the surface, then traverses the inner table, and then determines whether the join conditions are met, and then determines whether to spit out the records to the last execution node. In terms of algorithm, this is a complexity of M * n. Hash join is an optimization for equal join scenarios. The basic idea is to load the external data into memory and establish a hash table. In this way, you can complete the join operation and output the matching records only by traversing the internal table once. If all the data can be loaded into memory, of course, the logic is simple. Generally speaking, this kind of join is called CHJ (classic hash join). MariaDB has implemented this kind of hash join algorithm before. If all the data cannot be loaded into memory, it needs to be loaded into memory in batches, and then joined in batches. The following describes the implementation of these join algorithms.

In-Memory Join(CHJ)

HashJoin一般包括两个过程,创建hash表的build过程和探测hash表的probe过程。

1).build phase

遍历外表,以join条件为key,查询需要的列作为value创建hash表。这里涉及到一个选择外表的依据,主要是评估参与join的两个表(结果集)的大小来判断,谁小就选择谁,这样有限的内存更容易放下hash表。

2).probe phase

hash表build完成后,然后逐行遍历内表,对于内表的每个记录,对join条件计算hash值,并在hash表中查找,如果匹配,则输出,否则跳过。所有内表记录遍历完,则整个过程就结束了。过程参照下图,来源于MySQL官方博客

左侧是build过程,右侧是probe过程,country_id是equal_join条件,countries表是外表,persons表是内表。

On-Disk Hash Join

CHJ的局限性在于需要内存来适应整个曲面。在mysql中,join可以使用的内存由join buffer size参数控制。如果一个连接所需的内存超过了连接缓冲区的大小,CHJ会忍不住将曲面分成几个段,逐个构建每个段,然后遍历内部表,再次探测每个段。假设表面被分成n块,然后扫描内表n次。当然,这种方式比较弱。在MySQL 8.0中,如果一个join所需的内存超过了join缓冲区的大小,那么构建阶段将首先使用哈希计算来划分外表面并生成一个临时的磁盘分区;然后在探测阶段,使用相同的哈希算法来划分内表。由于相同的哈希函数,相同的键(相同的连接条件)必须在相同的分区号中。接下来,对外部表和内部表中具有相同分区号的数据执行CHJ。在所有的CHJ片段完成之后,整个连接过程就完成了。该算法的代价是外部表读IO两次,内部表写IO一次。与以往的n扫描内表IO相比,目前的处理方法更好。


#include<cstdio>

#include<algorithm>

#include<queue>

#include<cstring>

using namespace std;

struct data

{

    int to,next,val;

}e[2*100005];

int cnt,head[10005],prep[10005],pree[10005],flow[10005],ans;

queue<int> que;

int n,m,s,t,u,v,w;

void add(int u,int v,int w)

{

    e[++cnt].to=v;

    e[cnt].next=head[u];

    head[u]=cnt;

    e[cnt].val=w;

}

int bfs(int s,int t)

{

    while (!que.empty()) que.pop();

    flow[s]=0x3f3f3f3f;//flow记录的是在增广路上经过该点的流量

    que.push(s);

    for (int i=1;i<=n;i++) 

    {

        prep[i]=-1;//用于记录前驱节点

        pree[i]=0;//用于记录前驱边的编号

    }

    prep[s]=0;

    while (!que.empty())

    {

        int now=que.front();

        que.pop();

        if (now==t) break;

        for (int i=head[now];i;i=e[i].next)

        {

            if (e[i].val>0&&prep[e[i].to]==-1)

            {

                que.push(e[i].to);

                flow[e[i].to]=min(flow[now],e[i].val);

                pree[e[i].to]=i;

                prep[e[i].to]=now;

            }

        }

    }

    if (prep[t]!=-1) return flow[t];

    else return -1;

}

void EK(int s,int t)

{

    int delta=bfs(s,t);//寻找最短增广路的最大流量

    while (delta!=-1)

    {

        ans+=delta;

        for (int j=t;j;j=prep[j])

        {

            e[pree[j]].val-=delta;

            e[pree[j]^1].val+=delta;

            //链式前向星存边从编号2开始存储可以通过异或1快速取得反向边的编号。

        }

        delta=bfs(s,t);

    }

}

int main()

{

    scanf("%d%d%d%d",&n,&m,&s,&t);

    cnt=1;

    for (int i=1;i<=m;i++)

    {

        scanf("%d%d%d",&u,&v,&w);

        add(v,u,0);

        add(u,v,w);

        //加入正反边

    }



## 总结

一般像这样的大企业都有好几轮面试,所以自己一定要花点时间去收集整理一下公司的背景,公司的企业文化,俗话说「知己知彼百战不殆」,不要盲目的去面试,还有很多人关心怎么去跟HR谈薪资。

这边给大家一个建议,如果你的理想薪资是30K,你完全可以跟HR谈33~35K,而不是一下子就把自己的底牌暴露了出来,不过肯定不能说的这么直接,比如原来你的公司是25K,你可以跟HR讲原来的薪资是多少,你们这边能给到我的是多少?你说我这边希望可以有一个20%涨薪。

最后再说几句关于招聘平台的,总之,简历投递给公司之前,请确认下这家公司到底咋样,先去百度了解下,别被坑了,每个平台都有一些居心不良的广告党等着你上钩,千万别上当!!!

Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://codechina.csdn.net/m0_60958482/java-p7)**

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
bbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://codechina.csdn.net/m0_60958482/java-p7)**

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
![在这里插入图片描述](https://img-blog.csdnimg.cn/img_convert/8ad636486a32704ceec03d3c98b5be2d.png)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值