MySQL 统计信息不准导致的性能问题

表的统计信息错误导致优化器选择错误的执行计划。

一个客户的性能优化案例: 没有修改数据库实例的任何配置参数以及业务代码没有变更的情况下,一条 sql 出现大幅性能下降。

我们来看看出问题的sql 以及他的执行计划:

mysql> explain 
-> SELECT count(con.id)          ,
->        MAX(DAYNAME(con.date)) ,
->        now()                  ,
->        pcz.type,
->        pcz.c_c
-> FROM   con AS con
->        join orders o on con.o_id = o.id
->        JOIN pcz AS pcz ON o.d_p_c_z_id = pcz.id
->        left join c c on con.c_id = c.id
-> WHERE con.date = current_date() and pcz.type = "T_D"
-> GROUP BY con.date, pcz.c_c,  pcz.type;
+----+-------------+-------+------------+--------+-------------------+----------+---------+----------------------------+------+----------+----------------------------------------------+
| id | select_type | table | partitions | type   | possible_keys     | key      | key_len | ref                        | rows | filtered | Extra                                        |
+----+-------------+-------+------------+--------+-------------------+----------+---------+----------------------------+------+----------+----------------------------------------------+
|  1 | SIMPLE      | pcz   | NULL       | ALL    | PRIMARY           | NULL     | NULL    | NULL                       |  194 |    10.00 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | o     | NULL       | ref    | PRIMARY,dpcz_FK   | dpcz_FK  | 9       | custom.pcz.id              | 1642 |   100.00 | Using index                                  |
|  1 | SIMPLE      | con   | NULL       | ref    | FK_order,IDX_date | FK_order | 8       | custom.o.id                |    1 |     4.23 | Using where                                  |
|  1 | SIMPLE      | c     | NULL       | eq_ref | PRIMARY           | PRIMARY  | 8       | custom.con.c_id            |    1 |   100.00 | Using index                                  |
+----+-------------+-------+------------+--------+-------------------+----------+---------+----------------------------+------+----------+----------------------------------------------+


执行计划显示 rows examined = (19410%)1642(14.23%)=1347 查看执行计划我们就发现 where 条件 con.date = current_date() 。这个条件看起来更适合作为索引过滤数据。但是 为什么 MySQL 优化器不选择该索引呢?接下来使用 force index 强制执行计划使用 con.date 字段上的索引。执行计划如下:

mysql> explain 
-> SELECT count(con.id)          ,
->        MAX(DAYNAME(con.date)) ,
->        now()                  ,
->        pcz.type,
->        pcz.c_c
-> FROM   con AS con USE INDEX(IDX_date)
->        join orders o on con.o_id = o.id
->        JOIN p_c_z AS pcz ON o.d_p_c_z_id = pcz.id
->        left join c c on con.c_id = c.id
-> WHERE con.date = current_date() and pcz.type = "T_D"
-> GROUP BY con.date, pcz.c_c,  pcz.type;
+----+-------------+-------+------------+--------+-----------------+----------+---------+---------------------------------------+--------+----------+---------------------------------+
| id | select_type | table | partitions | type   | possible_keys   | key      | key_len | ref                                   | rows   | filtered | Extra                           |
+----+-------------+-------+------------+--------+-----------------+----------+---------+---------------------------------------+--------+----------+---------------------------------+
|  1 | SIMPLE      | con   | NULL       | ref    | IDX_date        | IDX_date | 3       | const                                 | 110446 |   100.00 | Using temporary; Using filesort |
|  1 | SIMPLE      | c     | NULL       | eq_ref | PRIMARY         | PRIMARY  | 8       | custom.con.c_id                       |      1 |   100.00 | Using index                     |
|  1 | SIMPLE      | o     | NULL       | eq_ref | PRIMARY,dpcz_FK | PRIMARY  | 8       | custom.con.o_id                       |      1 |   100.00 | Using where                     |
|  1 | SIMPLE      | pcz   | NULL       | eq_ref | PRIMARY         | PRIMARY  | 8       | custom.o.d_p_c_z_id                   |      1 |    10.00 | Using where                     |
+----+-------------+-------+------------+--------+-----------------+----------+---------+---------------------------------------+--------+----------+---------------------------------+

问题来了 rows examined = 110446*(1*10%)=11045 rows根据计算评估, 第一个执行计划的 1347 大概是 110446 的十分之一 ,至少从表面上看来这个是MySQL 优化器选择第一个执行计划的原因。

但是对比实际的查询结果的响应时间,肯定粗问题了。因为执行计划二 的sql 的响应时间在预期之内,但是执行计划一对应的响应时间反而更慢。

进一步来看表 orders 的创建语句以及执行计划1,我们发现 表pcz的确有194行。然后查看 索引 orders.dpcz_FK,表 orders 返回 1642行 ,因为外键约束 orders_ibfk_10 的定义,也就意味着 表 orders 的记录数应该是 194*1642=318548 ,但是实际的行数是 32508150,百倍于执行计划估计的值 318548 。

CREATE TABLE `orders` (`id` bigint(20) NOT NULL AUTO_INCREMENT,...`d_p_c_z_id` bigint(20) DEFAULT NULL,...,PRIMARY KEY (`id`),...KEY `dpcz_FK` (`d_p_c_z_id`),...CONSTRAINT `orders_ibfk_10` FOREIGN KEY (`d_p_c_z_id`) REFERENCES `p_c_z` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,...
) ENGINE=InnoDB ....
mysql> select * from mysql.innodb_table_stats  where database_name='cutom' and table_name='orders';
+---------------+------------+---------------------+----------+----------------------+--------------------------+
| database_name | table_name | last_update         | n_rows   | clustered_index_size | sum_of_other_index_sizes |
+---------------+------------+---------------------+----------+----------------------+--------------------------+
| custom        | orders     | 2022-03-03 21:58:18 | 32508150 |               349120 |                   697618 |
+---------------+------------+---------------------+----------+----------------------+--------------------------+


分析至此,我们可以断定 orders.dpcz_FK 的统计信息是不准确的,于是乎我们使用如下语句确认它的实际数据量:

mysql> select * from mysql.innodb_index_stats where database_name='cutom' and table_name='orders' and index_name='dpcz_FK';
mysql> select * from mysql.innodb_index_stats  where database_name='custom' and table_name='orders' and index_name='dpcz_FK';
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| custom        | orders     | dpcz_FK    | 2022-02-28 12:35:30 | n_diff_pfx01 |      19498 |          50 | d_p_c_z_id                        |
| custom        | orders     | dpcz_FK    | 2022-02-28 12:35:30 | n_diff_pfx02 |   32283087 |         128 | d_p_c_z_id,id                     |
| custom        | orders     | dpcz_FK    | 2022-02-28 12:35:30 | n_leaf_pages |      55653 |        NULL | Number of leaf pages in the index |
| custom        | orders     | dpcz_FK    | 2022-02-28 12:35:30 | size         |      63864 |        NULL | Number of pages in the index      |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
mysql> select count(distinct d_p_c_z_id) from orders; 
+----------------------------------------------+
| count(distinct d_p_c_z_id)                   |
+----------------------------------------------+
|                                          195 |
+----------------------------------------------+

Bingo!从上面来看 表 orders 字段 d_p_c_z_id 的区分度(不一样的值的总数)为 195 。在信息统计表里面 dpcz_FK的 stat_value 值是 19498 ,显然这个值是不准确的并且比实际值大的多,100倍 。索引的 state_value 值应该等于这个字段的在表里面的区分度。

如果使用正确的 索引 dpcz_FK 的值 stat_value 195 去重新评估执行计划的成本,我们将得到执行计划1 的结果 32508150/195=166708 ,并且执行计划预估的扫描的行数应该是 (194*10%)*166708*(1*4.23%)=136804。因为该值是10倍于执行计划2 的值 11045 。MySQL 在没有使用force index的情况下就能走到正确的执行计划 。

这个sql的问题解决了,但是为什么 MySQL 的统计信息会计算错误,我们如何修复它呢?

回答这个问题之前,我们先了解一下 MySQL 是如何收集统计信息以及哪些参数控制 这个动作。

InnoDB 是如何收集表的统计信息

我们可以通过显式的方式或者系统自动采集表的统计信息 。

通过开启参数innodb_stats_auto_recalc =on (默认也是打开的) 以便在表的数据发生重大变化以后来自动收集表的统计信息。比如当表中的10% 的行发生变化 ,InnoDB 将重新计算统计信息。或者我们可以使用ANALYZE TABLE显式地重新计算统计信息。

InnoDB 使用随机采样技术的方法采集统计信息-- 随机抽取索引页,估计索引的基数。参数 innodb_stats_persistent_sample_pages 控制采样页面的数量。参考 https://dev.mysql.com/doc/refman/5.7/en/innodb-persistent-stats.html

根据代码和描述,随机抽样并不是完全随机的。采样页面实际上是根据采样算法选择的。最终,不同键值的总数,即索引的 stat_value 将通过以下公式计算
N * R * N_DIFF_AVG_LEAF。其中

N : 叶页数
R : level LA上不同key值的个数与level LA上记录总数的比值
`N_DIFF_AVG_LEAF`:在所有 A 叶页中找到的不同键值的平均数。

采样算法代码的详细信息可以在链接中找到:https://github.com/mysql/mysql-server/blob/6846e6b2f72931991cc9fd589dc9946ea2ab58c9/storage/innobase/dict/dict0stats.cc

基于上面的介绍,我们知道当一个表的索引发生分裂时,无论是叶子页数(N),还是 层LA 上不同键值的个数占 层LA 总记录数的比值(R ) 变得越来越不准确,因此 stat_value 的计算可能不正确。一旦发生这种情况,除非更改参数innodb_stats_persistent_sample_pages或重建索引,否则显式重新计算(手动运行 ANALYZE TABLE)将无法生成正确的 stat_value。

解决方法

我们怎么修正表的统计信息 ,并且阻止这类情况进一步发生。

经过前面的分析和讨论,我们知道 有两个因素影响数据库收集表的统计信息 ,

innodb_stats_persistent_sample_pages: A
索引的组织方式

为了能够让 InnoDB 得到正确的 统计信息,我们需要 调整 innodb_stats_persistent_sample_pages 或者重建索引 。

通过命令 analyze table 不重建的方式,保持 innodb_stats_persistent_sample_pages =128,stat_value 略微更改为 19582,接近原始不正确的 19498,仍然关闭。索引中的叶子页数从 55653 略微更改为 55891,索引中的页数也从 63864 略微更改为 64248

mysql> show variables = 'innodb_stats_persistent_sample_pages;
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_stats_persistent_sample_pages | 128   |
+--------------------------------------+-------+
mysql> analyze table orders;
+---------------+---------+----------+----------+
| Table         | Op      | Msg_type | Msg_text |
+---------------+---------+----------+----------+
| custom.orders | analyze | status   | OK       |
+---------------+---------+----------+----------+
mysql> select * from mysql.innodb_index_stats  where database_name='custom' and table_name='orders' and index_name='dpcz_FK';
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| custom        | orders     | dpcz_FK    | 2022-03-03 21:58:18 | n_diff_pfx01 |      19582 |          50 | d_p_c_z_id                        |
| custom        | orders     | dpcz_FK    | 2022-03-03 21:58:18 | n_diff_pfx02 |   32425512 |         128 | d_p_c_z_id,id                     |
| custom        | orders     | dpcz_FK    | 2022-03-03 21:58:18 | n_leaf_pages |      55891 |        NULL | Number of leaf pages in the index |
| custom        | orders     | dpcz_FK    | 2022-03-03 21:58:18 | size         |      64248 |        NULL | Number of pages in the index      |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+

ANALYZE TABLE 不重建,但将 innodb_stats_persistent_sample_pages 从 128 增加到 512,使 stat_value 到192非常接近实际基数 195。索引中的叶页数发生了很大变化,从 55653 到 44188。索引中的页数也从也发生了巨大变化,从 63864 变为 50304。

mysql> show variables like '%persistent_sample%';
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_stats_persistent_sample_pages | 512   |
+--------------------------------------+-------+
mysql> analyze table orders;
+---------------+---------+----------+----------+
| Table         | Op      | Msg_type | Msg_text |
+---------------+---------+----------+----------+
| custom.orders | analyze | status   | OK       |
+---------------+---------+----------+----------+
mysql> select * from mysql.innodb_index_stats  where database_name='custom' and table_name='orders' and index_name='dpcz_FK';
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| custom        | orders     | dpcz_FK    | 2022-03-09 06:54:29 | n_diff_pfx01 |        192 |         179 | d_p_c_z_id                        |
| custom        | orders     | dpcz_FK    | 2022-03-09 06:54:29 | n_diff_pfx02 |   31751321 |         512 | d_p_c_z_id,id                     |
| custom        | orders     | dpcz_FK    | 2022-03-09 06:54:29 | n_leaf_pages |      44188 |        NULL | Number of leaf pages in the index |
| custom        | orders     | dpcz_FK    | 2022-03-09 06:54:29 | size         |      50304 |        NULL | Number of pages in the index      |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+

重建表,保持 innodb_stats_persistent_sample_pages 为128,同样得到了正确的 stat_value 187,接近真实基数195。索引中的叶子页数大幅变化,从55653变为43733,索引中的页数也从63864变化到 50111。

mysql> show variables = 'innodb_stats_persistent_sample_pages';
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_stats_persistent_sample_pages | 128   |
+--------------------------------------+-------+
mysql> alter table orders engine=innodb;
Query OK, 0 rows affected (11 min 16.37 sec)
mysql> select * from mysql.innodb_index_stats where database_name='custom' and table_name='orders' and index_name='dpcz_FK';
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| custom        | orders     | dpcz_FK    | 2022-03-07 18:44:43 | n_diff_pfx01 |        187 |         128 | d_p_c_z_id                        |
| custom        | orders     | dpcz_FK    | 2022-03-07 18:44:43 | n_diff_pfx02 |   31531493 |         128 | d_p_c_z_id,id                     |
| custom        | orders     | dpcz_FK    | 2022-03-07 18:44:43 | n_leaf_pages |      43733 |        NULL | Number of leaf pages in the index |
| custom        | orders     | dpcz_FK    | 2022-03-07 18:44:43 | size         |      50111 |        NULL | Number of pages in the index      |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+

在更正表统计数据后,MySQL 优化器也会选择正确的执行计划:

mysql> explain
SELECT count(con.id)          ,MAX(DAYNAME(con.date)) ,now()                  ,pcz.type,pcz.c_c
FROM con AS conjoin orders o on con.order_id = o.idJOIN p_c_z AS pcz ON o.d_p_c_z_id = pcz.idleft join c c on con.c_id = c.id
WHERE con.date = current_date()
and pcz.type = "T_D"
GROUP BY con.date, pcz.c_c,  pcz.type;
+----+-------------+-------+------------+--------+-------------------+----------+---------+---------------------------------------+------+----------+---------------------------------+
| id | select_type | table | partitions | type   | possible_keys     | key      | key_len | ref                                   | rows | filtered | Extra                           |
+----+-------------+-------+------------+--------+-------------------+----------+---------+---------------------------------------+------+----------+---------------------------------+
|  1 | SIMPLE      | con   | NULL       | ref    | FK_order,IDX_date | IDX_date | 3       | const                                 | 3074 |   100.00 | Using temporary; Using filesort |
|  1 | SIMPLE      | c     | NULL       | eq_ref | PRIMARY           | PRIMARY  | 8       | custom.con.c_id                       |    1 |   100.00 | Using index                     |
|  1 | SIMPLE      | o     | NULL       | eq_ref | PRIMARY,dpcz_FK   | PRIMARY  | 8       | custom.con.order_id                   |    1 |   100.00 | Using where                     |
|  1 | SIMPLE      | pcz   | NULL       | eq_ref | PRIMARY           | PRIMARY  | 8       | custom.o.d_p_c_z_id                   |    1 |    10.00 | Using where                     |
+----+-------------+-------+------------+--------+-------------------+----------+---------+---------------------------------------+------+----------+---------------------------------+
4 rows in set, 1 warning (0.01 sec)

结论

MySQL优化器依赖于表的统计信息的准确性来选择最优的执行计划。我们可以通过更改参数 innodb_stats_persistent_sample_pages 来控制系统采集表统计信息的准确性。

我们还可以选择通过在对索引进行碎片整理的同时重建/重建表来强制重新计算表统计信息,这有助于提高表统计信息的准确性。重构表,我们可以直接用 alter table xx; 修改表或者使用 pt-online-schema-change 达到同样的效果。

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510568.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设z=〖(1+xy)〗^y,求 ∂z/∂y

z〖(1xy)〗^y lnzyln(1+xy) 两边同时对y求偏导,得 1/z ∂z/∂yln(1+xy)+y1/(1+xy) x 1/z ∂z/∂yln(1+xy)&…

基于 RTS 超低延时直播优化强互动场景体验

RTS 在阿里云视频直播的基础上进行底层技术优化,通过集成阿里云播放器 SDK,支持在千万级并发场景下节点间毫秒级延时直播的能力,弥补了传统直播存在 3~6 秒延时的问题,确保了超低延时、低卡顿、秒开流畅的直播观看体验。本文介绍了…

一文详解用 eBPF 观测 HTTP

前言 随着eBPF推出,由于具有高性能、高扩展、安全性等优势,目前已经在网络、安全、可观察等领域广泛应用,同时也诞生了许多优秀的开源项目,如Cilium、Pixie等,而iLogtail 作为阿里内外千万实例可观测数据的采集器&…

图像格式jpg、jpeg、jpe、gif、png、png等有何不同?ps中那种图片格式可以保留图层?

(1)jpg格式:即为jpeg格式,是通过压缩改变画质和文件尺寸的格式。压缩后恶化的图像无法还原,使用于数字图像及Web中的照片中。(2)jpeg格式:是目前网络上最流行的图像格式,…

面向云时代的龙蜥操作系统,是 CentOS 替代的最佳选择

2022 开放原子全球开源峰会 OpenAnolis 分论坛上,阿里云智能基础软件产品经理张鹏程做了《面向云时代的龙蜥操作系统,应对 CentOS 停服的最佳选择》的主题分享,介绍了操作系统产业迎来新发展格局,龙蜥致力于成为 CentOS 迁移的最佳…

数据库治理利器:动态读写分离

背景 在分布式系统架构中,业务的流量都是端到端的。每个请求都会经过很多层处理,比如从入口网关再到 Web Server 再到服务之间的调用,再到服务访问缓存或 DB 等存储。 对于我们的系统来说,数据库是非常重要的一块。因此无论是在稳…

const与define之间的区别?

const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。 举例:cons…

为什么我要迁移 SpringBoot 到函数计算

为什么要迁移? 我们的业务有很多对外提供服务的 RESTful API,并且要执行很多不同的任务,例如同步连锁 ERP 中的商品信息到美团/饿了么等平台,在线开发票等。由于各种 API 和任务执行的不确定性,经常会因为资源不足导致…

Ingress Nginx 接连披露高危安全漏洞,是否有更好的选择?

今年 K8s Ingress Nginx 项目接连披露了三个高危安全漏洞(CVE-2021-25745[1], CVE-2021-25746[2], CVE-2021-25748[3]),该项目也在近期宣布将停止接收新功能 PR,专注修复并提升稳定性。Ingress Nginx 作为 K8s 项目自带的网关组件…

链表c++代码的实现

//说明:各位测试数据的时候,请严格按照主函数来测试数据。因为这个链表是假设所有输入数据正确的情况。。。假如随便乱输入的话。。我没写边界检查。 //本次写法是比较简洁的。方便大家学习。 #include "iostream" using namespace std; typedef struct …

浅谈数据仓库架构设计

1. 数据中台与DW/BI/DSS 个人认为数据中台本质上是一种新的适配大数据技术发展的新的“数据仓库-决策支持(商业智能)”架构。这个架构是构建在传统的架构基础之上,对传统架构的一种新的发展。 数据中台从企业的视角出发,要求企业…

RocketMQ 消息集成:多类型业务消息 - 定时消息

引言 Apache RocketMQ 诞生至今,历经十余年大规模业务稳定性打磨,服务了 100% 阿里集团内部业务以及阿里云数以万计的企业客户。作为金融级可靠的业务消息方案,RocketMQ 从创建之初就一直专注于业务集成领域的异步通信能力构建。 本篇将继续…

一文读懂 BizDevOps:数字化转型下的技术破局

我们正迈向数字经济时代,数字化转型成为普遍行动。未来绝大多数业务都将运行在数字基座之上,软件系统成为业务创新和发展的核心引擎。在这一趋势下,产品研发的交付能力面临巨大挑战,产品研发的交付实践和方法亟待变革。 BizDevOp…

栈c++代码实现

//实在不想写数组法了&#xff0c;写个常用的STL的吧 #include "iostream" #include "algorithm" #include "stack" using namespace std; void Init(stack <int> s) { while(!s.empty()) { s.pop(); } } int main() { stack …

地址标准化服务AI深度学习模型推理优化实践

导读 深度学习已在面向自然语言处理等领域的实际业务场景中广泛落地&#xff0c;对它的推理性能优化成为了部署环节中重要的一环。推理性能的提升&#xff1a;一方面&#xff0c;可以充分发挥部署硬件的能力&#xff0c;降低用户响应时间&#xff0c;同时节省成本&#xff1b;…

PS里建立工作路径对话框中的“容差”是干什么的?

这里的容差是指&#xff1a;将选区转换为路径时的平滑程度&#xff0c;容差越大&#xff0c;平滑越重&#xff1b;容差越小&#xff0c;越精确&#xff08;与原选区对照&#xff09;&#xff0c;越接近你画的选区。PS的容差用在不同的地方&#xff0c;有不同的用法&#xff0c;…

淘系数据模型治理最佳实践

导读&#xff1a;本次分享题目为淘系数据模型治理&#xff0c;主要介绍过去一年淘系数据治理工作的一些总结。 具体将围绕以下4部分展开 模型背景&问题2问题分析3治理方案4未来规划 模型背景&问题 1.整体情况 首先介绍一下淘系的整体数据背景。 淘系的数据中台成立…

【走进RDS】之SQL Server性能诊断案例分析

客户的困扰 前几天某程序员小王向阿里云咨询他的SQL Server数据库整体负载较高&#xff0c;是否有优化的方法&#xff1f;前几天另外一个工单则是需要阿里云工程师帮忙定位某一个时刻的数据库性能尖刺的问题。 这些都是常见的性能诊断工单&#xff0c;其实数据库性能诊断不仅…

题目1335:闯迷宫( BFS在求解最短路径或者最短步数上有很多的应用)

题目描述&#xff1a;sun所在学校每年都要举行电脑节&#xff0c;今年电脑节有一个新的趣味比赛项目叫做闯迷宫。 sun的室友在帮电脑节设计迷宫&#xff0c;所以室友就请sun帮忙计算下走出迷宫的最少步数。 知道了最少步数就可以辅助控制比赛难度以及去掉一些没有路径到达终点的…

用了那么久的 Lombok,你知道它的原理么?

序言 在写Java代码的时候&#xff0c;最烦写setter/getter方法&#xff0c;自从有了Lombok插件不用再写那些方法之后&#xff0c;感觉再也回不去了&#xff0c;那你们是否好奇过Lombok是怎么把setter/getter方法给你加上去的呢&#xff1f;有的同学说我们Java引入Lombok之后会…