为什么查询数据不多,却慢的离谱,在我请教了隔壁新来的阿里大佬后

本文探讨MySQL查询缓慢的原因,包括MDL锁、FLUSH操作、行锁及索引不当等问题,并提供解决策略,如使用慢查询日志和调整事务隔离级别。

本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等

这篇文章主要记录,造成查询数量不大的情况下,造成查询缓慢的原因,以及相应的解决方法。

环境说明:

MySQL 版本 5.7.27
隔离级别:RR

锁等待造成查询速度很慢

MDL 锁

如开启如下事务:

Session A 持有表 t MDL 写锁。Session B 需要 MDL 读锁。这时读写锁互斥,Session B 被阻塞。

flush 阻塞

flush 操作一般来说很快就能执行完,当通过查询进程状态后,看到被 flush 操作被阻塞,一般都是由其他语句引起的。

如下面事务:

Session A 在扫描每一行时会休眠1s,而 Session B 的 flush tables t; 需要关闭表 t,要等 Session A 结束。后面的 Session C 被 Session B 阻塞了。

flush 的操作示范:

#  flush 表 t
flush tables t with read lock;
# flush 所有表
flush tables with read lock;
flush 的作用在 全局锁 文章中已经介绍过,FTWRL 主要用于 MyISAM 这样不支持事务的引擎,保证在备份时视图数据一致性。

行锁

这里的行锁,用两阶段锁来体现。其他如间歇锁和 next-key 锁都会可以造成这样的现象。

Session A 拥有 id=1 这行的写锁,Session B 想要拥有这一行的读锁,读写锁互斥。

解决方法

首先通过 show processlist; 命令查询被阻塞的状态信息。如需进一步分析的话,可以将 performance_schema=on 打开,通过查询 select blocking_pid from sys.schema_table_lock_waits; 具体造成锁等待的原因。然后 kill掉相应的 session.

在打开 performance_schema 会有一定的性能损失。

查询确实慢

没有设置合适的索引

如果没有设置合适的索引,导致扫描行数过多,时间自然就慢了。对于这种情况,可以开启慢查询日志,查看语句的执行过程,然后进行分析。

默认情况,慢查询日志时关闭的,打开方式如下:

# 查询慢查询日志状态及存储位置
# show variables  like '%slow_query_log%';

# 查询慢查询日志的设置时间
show variables  like '%long_query%';

# 临时打开慢查询日志,MySQL 重启后失效
set global slow_query_log=1;

# 改变时间
set long_query_time=0;

事务隔离的影响

在事务究竟有没有被隔离这篇中,我们知道表中的每行数据都有多个版本,在一致性视图开启后,视图的一致性读的结果就是通过和数据行的版本比较进而显示的结果。

这时第一个 select 语句就会比第二个加锁的 select 语句还要慢。

因为第一个 select 语句是一致性读,需要从 100 万条回滚日志中比较直到找到适合的版本。

而第二个 select 语句是当前读,直接读取最新版本就可以了。所以花费的时间不一样。

总结

造成查询小数据量,却很缓慢的原因一般有两种,第一种可能是所查数据被锁住。另一种确实是查找过程是真的很慢。

对于数据被锁住的情况,一般会由 MDL 锁,FLUSH 操作被阻塞,行锁造成。

对于查询确实很慢来说,考虑下索引是否设置的合适。并注意在 RR 级别下,是否由于一致性读和当前读的不同而造成查询速度不一致的情况。

在分析原因时,可以通过进程状态以及 sys.innodb_lock_waits 中的信息,来做出相应的处理。

非常感谢您的反馈! --- ## 📌 问题重述 您指出:**问题二的输出结果“太离谱”**,可能表现为: - 某些线路分配的客车数量异常大; - 有些线路分配的客车数量为0,但实际需求并不存在; - 结果不具有实际意义,比如所有线路都分配了高载客量客车(如55座),或相反。 --- ## 🔍 原因分析(常见问题汇总) 以下是可能导致“结果离谱”的**常见原因**: --- ### ✅ 1. **需求矩阵设置不准确** 您使用的是如下方式计算 `daily_flow_matrix(i, j)`: ```matlab daily_flow_matrix(i, j) = daily_flow_rate * population(i) * 10000 * (population(j) / sum(population)); ``` 这表示 **城市i到城市j的客流 = i地市人口 × 流动率 × j地市人口占比**。 📌 **问题**:这种方式是“比例法”,假设人口流动完全按人口比例分配,但现实中: - 有些城市间往来频繁(如省会与地级市); - 有些城市间流动极少(如偏远山区); - 没有考虑实际交通需求、经济水平、地理距离等。 --- ### ✅ 2. **未考虑客车的运行次数(频率)** 当前模型中,我们是根据单次运力满足需求来设计运营方案: ```matlab sum(bus_vars(i, j, k) * capacity(k)) >= daily_flow_matrix(i, j) ``` 📌 **问题**:这个模型假设每辆车**每天只运行一次**。但现实中: - 每辆客车每天可运行多次; - 没有引入“运行次数”变量,导致模型倾向于分配过多车辆。 --- ### ✅ 3. **模型未设置车辆总数限制** 目前模型中没有限制: - 各地市拥有的客车总量; - 每种类型客车的最大可用数量。 📌 **问题**:模型可以任意分配车辆,可能导致: - 某一城市被分配远超其拥有的客车数; - 车辆被“重复使用”于多个线路。 --- ### ✅ 4. **目标函数仅考虑运输成本** 目标函数为: ```matlab objective = sum(bus_vars(i, j, k) * capacity(k) * dist(i, j)) ``` 📌 **问题**:这个目标函数等价于**最小化总运力 × 距离**,而非: - 最小化总客车数量; - 最小化总成本(含运行次数); - 均衡线路使用率。 --- ## ✅ 如何修复这些“离谱”结果? ### ✅ 修复建议 1:引入运行次数变量 假设每辆车每天最多运行 `max_runs_per_day` 次(例如 2 次),修改约束为: ```matlab total_capacity = sum(bus_vars(i, j, k) * capacity(k) * max_runs_per_day); ``` ### ✅ 修复建议 2:加入车辆数量限制 如果某地市拥有某类客车的数量为 `available_buses(city, type)`,则添加如下约束: ```matlab for j = 1:num_cities for k = 1:num_bus_types total_used = sum(sol.bus_vars(i, :, k)); % 地市 i 使用的 k 类客车数量 prob.Constraints.(['limit_', num2str(i), '_', num2str(k)]) = total_used <= available_buses(i, k); end end ``` ### ✅ 修复建议 3:使用更合理的客流分配方式 您可以使用如下方式分配客流: - 给定一个“流动矩阵” `flow_matrix(i, j)`,表示 i 到 j 的实际每日客流; - 用实际数据替代“人口比例法”。 ```matlab daily_flow_matrix = flow_matrix; % 由实际统计数据或调查数据给出 ``` ### ✅ 修复建议 4:优化目标函数 将目标函数改为: ```matlab objective = sum(bus_vars(i, j, k)); % 最小化总客车使用数量 ``` 或: ```matlab objective = sum(bus_vars(i, j, k) * cost_per_bus(k)); % 按照不同类型客车成本加权 ``` --- ## ✅ 示例:修正后的结果(合理模拟) ``` 最优营运方案: 从地市1到地市2的运营方案: 类型1的客车数量:0 类型2的客车数量:1 类型3的客车数量:1 类型4的客车数量:0 从地市1到地市3的运营方案: 类型1的客车数量:0 类型2的客车数量:0 类型3的客车数量:1 类型4的客车数量:0 从地市9到地市10的运营方案: 类型1的客车数量:0 类型2的客车数量:0 类型3的客车数量:1 类型4的客车数量:0 ``` > 🧠 **说明**:每条线路只使用1~2辆45座客车即可满足客流需求,符合实际逻辑。 --- ## ✅ 知识点总结 | 知识点 | 说明 | |--------|------| | **客流分配模型** | 人口比例法不准确,建议使用实际数据或引入距离、经济因子修正 | | **整数规划建模** | 使用 `optimproblem` 构建优化问题时,应考虑车辆数量、运行次数限制 | | **目标函数设置** | 可设置为最小化成本、最小化车辆使用、最小化总运行时间等 | | **变量维度与约束** | 多维变量需逐项构建,确保维度匹配,否则结果会“离谱” | --- 如您能提供实际的客流矩阵、车辆数量限制、运行次数上限等信息,我可以为您**重构建更合理的优化模型**并输出更**贴近实际的营运方案**!欢迎继续补充数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值