MySQL多表联合查询优化:从执行计划到索引设计的实战指南
简介MySQL多表联合查询效率分析及优化是一份面向数据库开发者与运维人员的PDF技术文档旨在解决多表关联查询中结果集膨胀、响应缓慢等常见问题。资源系统梳理了笛卡尔积、内连接、左/右外连接等连接类型的工作原理与适用场景并结合实际案例说明索引使用、EXPLAIN执行计划分析、LIMIT限制结果集、子查询替代连接、临时表与UNION优化等多项策略同时涵盖通过USE INDEX/IGNORE INDEX提示索引、避免OR条件导致索引失效等实用技巧。文档共1个PDF文件压缩包仅81KB内容紧凑、可直接对照实践。目前已有5456人学习下载适合正在排查慢查询、优化复杂报表SQL或准备面试的中高级MySQL使用者。通过阅读这份笔记读者可以快速建立多表查询的优化框架掌握从连接类型选择到执行计划调优的完整思路避免全表扫描并提升查询性能。1. 为什么多表联合查询会拖垮 MySQL先看这两类慢 SQL你在处理 mysql 慢查询日志时十有八九会遇到多表联合查询一条看似正常的 left join线上跑了几秒才出结果一个嵌套子查询测试环境数据量小没感觉复制到生产直接打满连接池。多表联合查询效率分析的核心不是背 join 语法而是搞清楚 MySQL 在连接两张表时到底选了哪条路、每步估算多少行、临时表落在内存还是磁盘。这里会从执行计划讲起把驱动表选择、索引设计、SQL 改写、深度分页这几个关键点逐个拆开最后给一套可以在本地复现的基准测试方法。适合刚开始做慢 SQL 优化的研发也适合被 DBA 追着要 explain 结果的业务开发。2. 多表联合查询的执行计划入门EXPLAIN 输出里该看哪几列2.1 驱动表和被驱动表小表驱动大表不是玄学拿到一条慢的多表查询先不要猜直接执行 EXPLAIN。执行计划会输出多行每一行对应一张表其中排在第一行的表通常就是驱动表。驱动表决定外层循环次数被驱动表决定每次嵌套查询的成本这两者的角色直接决定了最终耗时。EXPLAIN SELECT u.id, u.name, o.order_no FROM user u JOIN orders o ON o.user_id u.id WHERE u.phone LIKE 138%;执行后一般能看到第一行 tableu第二行 tableo。第一行是驱动表第二行是被驱动表。如果 u 表按 phone 过滤后剩 2000 行MySQL 会用这 2000 行去 orders 表按 user_id 逐次查找orders 表行数再多只要 user_id 有索引每次查找成本都近似一次 B 树搜索。外层循环次数越少总成本越低这就是“小表驱动大表”的本质。EXPLAIN FORMATJSON SELECT u.id, u.name, o.order_no FROM user u JOIN orders o ON o.user_id u.id WHERE u.phone LIKE 138%;FORMATJSON 会输出更细的 cost_info 和 used_key_parts适合在两张表看起来都有索引、但优化器仍然选错驱动表时用。参数方面如果 Extra 列出现 Using join buffer说明被驱动表匹配时用到了连接缓冲区先看一下当前 join_buffer_sizeSHOW VARIABLES LIKE join_buffer_size;调大 join_buffer_size 可以减少批量匹配次数但不要盲目调到几个 G内存压力会转嫁到排序和临时表。对于 inner join优化器会自动选择成本更小的驱动顺序对于 left join左表通常固定为驱动表如果右表 join 字段没有索引慢得非常直观。2.2 type 与 rows全表扫描和估算行数的坑EXPLAIN 的 type 字段是最快判断一个 JOIN 有没有走索引的依据。常见类型从好到差大致是const/eq_ref、ref、range、index、ALL。直接看表type含义多表 JOIN 场景const / eq_ref通过主键或唯一索引精确匹配被驱动表按主键关联时常见ref普通二级索引等值匹配被驱动表 join 列有非唯一索引range索引范围扫描where 里有 between、 等条件index全索引扫描覆盖索引可用但无法利用索引过滤ALL全表扫描join 列没索引或者索引失效rows 列是优化器估算的行数不是实际执行后返回的行数。很多新手看到 rows 很小就以为没救了其实如果 type 是 ALLrows 估算可能完全不准确。想拿真实执行行数可以改用 EXPLAIN ANALYZE这是 8.0.18 之后才有的功能EXPLAIN ANALYZE SELECT u.name, o.order_no FROM user u JOIN orders o ON o.user_id u.id WHERE u.id 12345;输出里会带 actual time、rows、loops 三类信息比如actual time0.123..0.456 rows3 loops1。rows 表示这一步实际生产了多少行loops 表示这个节点被循环执行了多少次两者乘起来才是真实数据量。至于 rows 估算偏了最常见的修法是对表重新做统计信息ANALYZE TABLE user, orders;执行完再跑 EXPLAINrows 通常会回归到接近实际值的水平。注意 EXPLAIN ANALYZE 会真正执行这条 SQL生产流量高峰时不要直接往主库上打最好在从库或测试环境跑。2.3 用 EXPLAIN 定位第一个需要优化的 JOIN慢 SQL 优化第一步不是改 SQL而是先定位慢在哪一张表。我一般会走这么几步开启慢查询日志收集慢 SQL到测试库上还原再 EXPLAIN最后根据 type 和 Extra 判断优先级。SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 1;开启后执行时间超过 1 秒的查询会进慢日志。生产环境用完记得关闭日志落盘本身也有开销。拿到慢 SQL 后在测试库前面加 EXPLAIN重点看三件事哪行 type 最差哪行 rows 最大Extra 里有没有 Using temporary、Using filesort、Using join buffer。以常见的两表 JOIN 为例如果第二行 orders 显示 typeALL说明被驱动表在按 user_id 关联时没有索引可用这往往是第一个要修的如果第一行 user 显示 ALL但它是驱动表优化器可能已经默认会扫全表来做批量匹配此时给 user 加索引未必能解决问题反而要先看 where 条件能不能收窄。真正定位时我习惯把 EXPLAIN 结果和业务 SQL 一起贴进文档表名、type、key、rows、Extra 各占一列这样优化前后对比时一眼就能看到变化。3. 三种常见多表查询优化手段从索引到改写3.1 索引设计JOIN 的 ON 字段和 WHERE 字段要分开看多表联合查询的索引设计和单表不一样。单表通常只看 where 条件多表还要多考虑一层驱动表靠 where 条件缩小结果集被驱动表靠 on 字段快速匹配。两者经常是不同字段所以不能只给一个字段建索引。举一个实际场景查询手机号以 138 开头、并且下过单的用户订单状态还需要是 PAID。SELECT u.id, u.name, o.order_no, o.status FROM user u JOIN orders o ON o.user_id u.id WHERE u.phone LIKE 138% AND o.status PAID;这种查询的索引设计可以分成两步。第一步在 user 表上给 phone 建索引让驱动表过滤从全表扫描变成 range 扫描ALTER TABLE user ADD INDEX idx_phone(phone);第二步在 orders 表上建联合索引让被驱动表既能按 user_id 快速匹配又能顺便过滤 statusALTER TABLE orders ADD INDEX idx_user_status(user_id, status);这样 join 时 orders 表不会再全表扫描status 过滤也能直接在索引层完成不需要每条记录回表判断。联合索引的字段顺序有讲究等值条件放前面范围条件放后面。user_id 在 on 里是等值条件status 在 where 里也是等值条件所以 (user_id, status) 比 (status, user_id) 更合适如果还有 order_no 精确匹配可以把 order_no 也加进去比如 (user_id, status, order_no)。建完索引先看SHOW INDEX FROM orders的 cardinality这个值表示索引去重后的估算值。如果 user_id 的基数很低比如一张表只有三五个用户那加索引的作用也有限反而白白增加写入成本。常见误用是给驱动表的 where 字段建了索引却忘了被驱动表的 on 字段结果是驱动表确实变小了但每次关联仍在扫大表整体毫无进步。3.2 让查询走覆盖索引减少回表的血泪经验覆盖索引优化是慢 SQL 优化里见效最快、也最容易被忽略的一招。所谓覆盖索引就是一条 SQL 需要读的所有列都落在同一个二级索引里InnoDB 不需要回主键聚簇索引就能拿到结果。SELECT u.id, u.name, o.order_no, o.status FROM user u JOIN orders o ON o.user_id u.id WHERE u.phone 13800001111;这查询里需要返回 user 表的 id、nameorders 表的 order_no、status还涉及 on 字段 user_id。相应的覆盖索引可以这样建ALTER TABLE user ADD INDEX idx_phone_name(phone, name); ALTER TABLE orders ADD INDEX idx_user_status_order(user_id, status, order_no);user 表的主键 id 会自动出现在二级索引叶子节点里所以 idx_phone_name 能覆盖 id、phone、name 三个字段orders 表的联合索引覆盖 user_id、status、order_no 以及主键 id。执行计划里 Extra 如果出现 Using index说明这个查询在索引里就把数据拿齐了。这里有一个血泪经验覆盖索引不是越宽越好。每多一个字段索引页就越宽B 树叶子节点能存放的条目就越少写入和更新时索引维护成本也越高。我一般只给 qps 排名靠前的两三类高频 JOIN 做覆盖索引不会把一张表所有查询都试图覆盖。另一个常见坑是 SELECT *一旦把不在索引里的字段带进去覆盖索引立刻失效MySQL 只能回表取剩余列。跑多表 JOIN 时先把你真正要用的列列出来别让 SELECT * 把优化成果直接冲掉。3.3 SQL 改写子查询、IN 和 JOIN 的取舍索引加到位之后如果 SQL 本身结构很差还是快不了。最常见的慢结构是相关子查询外层每取一行内层就执行一次子查询。比如统计下单超过 10 次的用户写成子查询是这个样子SELECT id, name FROM user u WHERE (SELECT COUNT(*) FROM orders o WHERE o.user_id u.id) 10;user 表有 10 万行这个子查询理论上会被执行 10 万次。即使 orders 有索引单次查询再快乘以 10 万也慢得吓人。常见做法是改写成 JOIN 加 GROUP BYSELECT u.id, u.name FROM user u JOIN orders o ON o.user_id u.id GROUP BY u.id, u.name HAVING COUNT(o.id) 10;改写后的逻辑是先把 user 和 orders 按 user_id 关联再对 user 分组统计orders 表整体只扫描一次。GROUP BY 可能会产生临时表但如果 user 表已经用 phone 或 status 过滤得很小临时表开销远小于原来的 10 万次子查询。改写时要注意语义等价。原相关子查询对没有订单的用户COUNT 为 0不会进入 HAVING 条件改写后的 INNER JOIN 本身也只保留有订单的用户两者结果一致。如果业务想保留没有订单的用户就要用 LEFT JOIN LEFT JOIN 后 COUNT 为 0 的行同样被 HAVING 过滤掉最终还是等价于 INNER JOIN改成 LEFT JOIN 只是多消耗临时表容量。MySQL 5.7 和 8.0 的优化器会把大部分 IN 子查询改写成 semi-join效果不一定差所以不要一看到子查询就改。正确的流程是先 EXPLAIN看子查询有没有被物化、有没有走索引再决定是否改写。多表查询常常会出现在事务处理链路里一条慢 SQL 拉长了整个事务导致行锁和间隙锁的持有时间变长这也是多表查询慢会连带引发锁等待的原因之一。4. 数据量增长后的多表联合查询从嵌套循环到临时表4.1 数据量增长后为什么 inner join 也会翻车很多人在测试环境只有几千行数据JOIN 怎么跑都快一到生产就原形毕露。原因在于嵌套循环 join 的复杂度是驱动表行数乘以被驱动表单次查询成本。两表都走索引时总成本近似等于 M 次索引查找驱动表行数从 1 万涨到 100 万总耗时也会跟着涨近百倍这是躲不掉的。最坏情况是被驱动表 join 字段没有索引MySQL 只能把两张表做笛卡尔式匹配成本接近 M×N。1 万行的表和 1 万行的表关联就是 1 亿次比较涨到 100 万就是万亿级别基本等于把数据库拖死。这也是为什么被驱动表的 join 字段索引优先级最高。MySQL 8.0.18 之后引入了 hash join在两张表做等值 inner join、且被驱动表没有可用索引时优化器会尝试用哈希连接代替嵌套循环EXPLAIN SELECT s.id, b.name FROM small_table s JOIN big_table b ON s.id b.small_id;如果 Extra 里出现 Using join buffer (hash join)说明这一步走的是 hash join。它对无索引场景确实有明显改善但哈希表要占内存内存不够时还要落磁盘反而可能更慢。在实际业务里不要指望 hash join 来救大表 JOIN核心仍然是把驱动表结果集缩小或者在被驱动表上建立索引。MySQL 的并行能力很弱单条 SQL 很难像其他数据库那样靠并行线程跑所以多表联合查询的优化重点应该放在减少扫描行数和避免大临时表上。4.2 group by 和 order by 在多表联查中的临时表问题多表 JOIN 之后再做 group by 或 order by是慢 SQL 的重灾区。MySQL 可能需要先把 join 后的中间结果放进临时表再对临时表排序或分组如果临时表超过内存阈值就会落到磁盘性能会断崖式下跌。EXPLAIN SELECT o.user_id, COUNT(*) FROM user u JOIN orders o ON o.user_id u.id WHERE u.status 1 GROUP BY o.user_id ORDER BY o.user_id;执行计划里如果出现 Using temporary 和 Using filesort说明中间结果已经进了临时表排序也没有直接走索引。这条 SQL 的问题在于过滤条件在 user 表分组和排序字段在 orders 表单索引很难同时满足两边的路径MySQL 只能先用 user 表过滤再把 join 结果整体缓存起来。EXPLAIN ANALYZE SELECT o.user_id, COUNT(*) FROM user u JOIN orders o ON o.user_id u.id WHERE u.status 1 GROUP BY o.user_id ORDER BY o.user_id;用 EXPLAIN ANALYZE 可以看到临时表这一步的真实耗时以及 rows 和 loops 的组合情况。常见的参数调整方向是先看 tmp_table_size 和 max_heap_table_size内存临时表超过这两个值就会转成磁盘临时表再看 sort_buffer_size它决定排序缓冲区。但调参只能缓解症状真正稳妥的做法是让 join 两侧的数据先各自收敛。比如先对 orders 表单独做分组统计再把结果和 user 表关联SELECT u.name, t.cnt FROM user u JOIN ( SELECT user_id, COUNT(*) cnt FROM orders GROUP BY user_id ) t ON u.id t.user_id ORDER BY t.cnt DESC;这样 orders 的分组发生在单表内索引可以直接支持 GROUP BY不会产生跨表的超大临时表user 表也只是在最后通过主键关联一次。ORDER BY 字段来自 t.cnt此时排序的数据量等于用户数而不是订单数。实践里这个改写对报表类查询提升非常明显。4.3 分页查询配合多表联查的深度翻页优化多表 JOIN 加 LIMIT 深度分页是另一个容易被忽视的性能黑洞。LIMIT 100000, 20 并不是只取 20 行而是先取前 100020 行再丢掉前面 10 万行如果前面这个排序还涉及多表 join代价就翻倍了。-- 优化前offset 10 万 SELECT u.id, u.name, o.order_no FROM user u JOIN orders o ON o.user_id u.id ORDER BY o.create_time DESC LIMIT 100000, 20;这个写法会把 user 和 orders 全部 join 完再按 create_time 排序最后丢弃前 10 万行。orders 表增长后join 和排序的开销都会被放大。常见做法是延迟关联先在子查询里只取主键再回表补列。-- 优化后子查询先拿主键再回表 SELECT u.id, u.name, o.order_no FROM ( SELECT id FROM orders ORDER BY create_time DESC LIMIT 100000, 20 ) tmp JOIN orders o ON tmp.id o.id JOIN user u ON u.id o.user_id ORDER BY o.create_time DESC;子查询里只 SELECT orders 主键 id可以走 orders 表上的二级索引 (create_time, id)在索引层面完成排序和跳过不需要把 user 表和 orders 表全量 join 一遍。拿到 20 个主键后再回表取 order_no并通过 user_id 关联 user 表最后只处理 20 行数据。这个写法对 mysql 排序场景尤其有效但有一个细节不能漏外部查询的 ORDER BY 字段必须和子查询里的排序字段一致否则 join 后行序可能被打乱。如果业务允许更好的方案是彻底放弃 offset改用游标分页每次带上上一次最后一条的 create_time用 WHERE create_time ? 加 LIMIT 20。对深度分页来说游标分页几乎是最优解缺点是用户不能直接跳页。5. 多表联合查询避坑指南5 个踩过的现场与排查方法5.1 字符集不一致导致 JOIN 全表扫描现象一条联表查询在测试环境很快到生产就慢得离谱EXPLAIN 里被驱动表 typeALLExtra 还出现 Using where。原因两张表的关联字段字符集不一致比如 user 表是 utf8mb4orders 表是 utf8MySQL 在比较时需要先做字符集转换导致索引无法直接使用。这个问题从 SHOW CREATE TABLE 里一眼就能看出来关联字段一个带 CHARACTER SET utf8mb4另一个带 CHARACTER SET utf8。解决统一两边字段的字符集和排序规则。比如把 orders 表关联字段改成 utf8mb4ALTER TABLE orders MODIFY user_id VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;大表上的字符集修改会重建表务必放在低峰期。改完之后再跑 EXPLAINtype 一般会从 ALL 回到 ref 或 eq_ref。5.2 隐式类型转换让索引失效现象WHERE 条件里传了一个数字给字符串字段SQL 跑得很慢EXPLAIN 显示 typeALL。原因字段是 VARCHAR但传入的是 INT 型参数MySQL 会自动把字段做类型转换转换后再比较索引就失效了。反过来也一样INT 字段传入字符串也可能触发同样的问题。解决先看表结构再改参数类型。比如 user_id 是 VARCHAR就写成字符串形式SELECT * FROM orders WHERE user_id 123456;不要在 SQL 里依赖 MySQL 的自动转换。写代码时也尽量让 ORM 参数和字段类型对齐排查时最有效的方法是直接对比 SQL 里的参数类型和表结构的字段类型。5.3 LEFT JOIN 的 NULL 值让结果集悄悄变大现象LEFT JOIN 返回的行数比左表还多或者在统计订单数量时数据对不上。原因LEFT JOIN 会保留左表所有行如果右表匹配到多行左表的一行会被复制成多份。另一个常见问题是右表字段是 NULL 时COUNT(右表字段) 不会把它算进去统计结果和预期不一致。解决先确认两表关联关系是一对一还是一对多。如果右表可能有多条记录先做聚合再去 JOIN。比如用户和订单是一对多统计用户订单数时要这样处理SELECT u.id, u.name, t.cnt FROM user u LEFT JOIN ( SELECT user_id, COUNT(*) cnt FROM orders GROUP BY user_id ) t ON u.id t.user_id;这样既保留没有订单的用户又不会让行数膨胀。业务上如果只关心有订单的用户直接用 INNER JOIN 更干净。5.4 SELECT * 让覆盖索引失效现象查询里只改了 SELECT *执行计划里本来应该有的 Using index 消失了响应时间明显变长。原因SELECT * 会把表里所有列都带出来覆盖索引覆盖不了那么多字段InnoDB 只能一条条回表补数据。多表 JOIN 中这个影响会被放大因为回表次数会乘以驱动表行数。解决只查询业务需要的列不要图一时方便用星号。比如只需要用户 id、姓名和订单号就明确列出SELECT u.id, u.name, o.order_no FROM user u JOIN orders o ON o.user_id u.id;优化完成后用 EXPLAIN 再确认一次 Extra 中是否出现 Using index如果没有说明覆盖索引还没完全生效继续检查有没有不必要的字段被带了出来。5.5 大表 COUNT JOIN 是个无底洞现象统计用户订单数量时直接用 LEFT JOIN 再 COUNTSQL 执行了几分钟都没回来。原因两张大表先做 JOIN 生成中间结果再对这个庞大的中间结果做 COUNT数据库扫描的行数可能达到千万甚至上亿级别。解决先聚合小表再关联大表。上面的用户订单统计写法已经演示过先对 orders 表 GROUP BY user_id得到每个用户订单数再和 user 表 LEFT JOIN。这本质上把“大表 JOIN 大表”变成了“大表先聚合再 JOIN 小表”扫描次数从笛卡尔级别降成一次全表分组加一次主键关联。对于这种统计类查询如果实时性要求不高更彻底的做法是维护一张汇总表订单写入时实时更新计数查询直接读汇总表。6. 最后一公里用 EXPLAIN ANALYZE 和基准数据把多表 JOIN 优化从经验变成结论6.1 造一份和你线上同分布的数据优化多表查询最怕在只有几百行数据的测试表上自我感动。我一般会先造一份和线上同分布的数据至少让驱动表有 10 万行以上被驱动表有几百万行并且字段之间的相关性也要模拟比如老用户订单多、新用户订单少而不是纯随机生成。DELIMITER $$ CREATE PROCEDURE gen_orders_test_data() BEGIN DECLARE i INT DEFAULT 1; SET autocommit0; WHILE i 500000 DO INSERT INTO orders(user_id, status, order_no, create_time) VALUES ( FLOOR(RAND()*100000)1, IF(RAND()0.5, PAID, CREATED), CONCAT(NO, i), NOW() - INTERVAL FLOOR(RAND()*365) DAY ); SET i i 1; END WHILE; COMMIT; END$$ DELIMITER ; CALL gen_orders_test_data();这里关闭 autocommit 按批插入500 万行能在可控时间内灌完。参数说明user_id 是 1 到 10 万的随机分布status 靠 RAND 制造 50% 的 PAID 比例create_time 散布在一年内。如果你的线上数据是偏斜的比如 top 10 用户占了 70% 订单就要把分布改成偏斜分布否则测出来的优化结论上生产会翻车。6.2 优化前后对比EXPLAIN ANALYZE 怎么看实际开销数据造好后把原始慢 SQL 和优化后的 SQL 都跑一遍 EXPLAIN ANALYZE重点记录三条信息actual time、rows、loops。actual time 是实际执行耗时rows 是每一步实际行数loops 表示这个节点循环了多少次。用一张表记录最直观方案type / keyactual timerowsloops优化前ALL / NULL约 1.2s5000001优化后ref / idx_user_status约 0.08s201EXPLAIN ANALYZE SELECT u.id, u.name, o.order_no FROM user u JOIN orders o ON o.user_id u.id WHERE u.phone 13800001111;注意 EXPLAIN ANALYZE 会真正执行 SQL建议在测试库跑不要在线上主库压测。6.3 还需要看并发mysqlslap 随手压一压单条 SQL 从 1 秒降到 80 毫秒不等于并发场景下经得住打。多表 JOIN 在并发下容易出现锁等待和连接积压我一般会用 mysqlslap 做一个快速冒烟测试mysqlslap -u root -p -h 127.0.0.1 \ --create-schematestdb \ --querySELECT ... \ --concurrency20 --iterations3concurrency 表示模拟 20 个并发连接iterations 表示跑 3 轮。如果发现平均耗时随并发明显上升就要回头检查事务隔离级别和索引锁范围。此时不能只盯着 EXPLAIN 里的 rows还要结合慢查询日志和连接数曲线判断。我最早优化多表查询习惯只盯着 rows 看觉得 rows 变小就完事了结果有几次临时表和排序才是真凶。现在我每次改动前都会先保存一份 EXPLAIN ANALYZE 的基线改完再对照一遍慢 SQL 有没有变快、扫描行数减没减、临时表消没消失全部一目了然。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

鸿蒙录音机开发实战:基于ArkTS与AudioCapturer实现

鸿蒙录音机开发实战:基于ArkTS与AudioCapturer实现

做鸿蒙应用开发有一段时间了,最近把一个经典的“录音机”Demo从零到一完整跑通了,从权限申请、AudioCapturer采集、WAV文件头封装、文件列表扫描到AVPlayer回放,一整条链路都亲手摸了一遍。录音机这个项目看似简单,其实是鸿蒙原生…

2026/10/13 22:14:54 阅读更多 →
便携式除湿机除湿量性能测试全流程:实验设计、数据处理与避坑实战

便携式除湿机除湿量性能测试全流程:实验设计、数据处理与避坑实战

把一台便携式除湿机放进房间开始测性能,听起来很简单——开机器、接水、按秒表,一天下来看水箱里有多少水就行。但真要把“除湿能力”测到一个能做横向对比、能指导产品改进的精度,事情就没那么轻松了。实际测试中会遇到功耗波动、空间湿度场…

2026/10/13 22:14:54 阅读更多 →
告别循环地狱:R语言Reduce函数与向量化操作实战

告别循环地狱:R语言Reduce函数与向量化操作实战

处理一批同结构的数据集时,大多数人第一步想的是for循环,第二步想到apply家族,但很少有人真正把Reduce和“向量化操作”玩明白。R 语言里处理多个数据集,最痛的并不是读取或合并,而是代码又长又慢,循环一层…

2026/10/13 22:14:54 阅读更多 →

最新新闻

A*算法在路径规划中的原理与实践优化

A*算法在路径规划中的原理与实践优化

1. 路径规划中的A*算法初探第一次接触A算法是在开发仓库机器人导航系统时。当时我们尝试了Dijkstra、深度优先搜索等各种路径规划方法,要么计算时间太长,要么找到的路径不够优化。直到一位同事推荐了A算法,测试效果令人惊艳——在100x100的网…

2026/10/14 2:22:24 阅读更多 →
ViTPose 仓库 DeepFashion 服装关键点检测实战:DeepPose + ResNet 回归模型配置与评估指南

ViTPose 仓库 DeepFashion 服装关键点检测实战:DeepPose + ResNet 回归模型配置与评估指南

人工智能计算机视觉深度学习 【免费下载链接】ViTPose The official repo for [NeurIPS22] "ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation" and [TPAMI23] "ViTPose: Vision Transformer for Generic Body Pose Estimation" 项…

2026/10/14 2:22:24 阅读更多 →
SimpMusic 的 Android 构建逻辑:用 Convention Plugins 与 Version Catalog 打造可扩展的 Gradle 构建体系

SimpMusic 的 Android 构建逻辑:用 Convention Plugins 与 Version Catalog 打造可扩展的 Gradle 构建体系

音视频 【免费下载链接】SimpMusic A cross-platform music app using YouTube Music for backend 项目地址: https://gitcode.com/gh_mirrors/si/SimpMusic 点击查看 免费下载 导读 本文围绕 SimpMusic 仓库中的构建配置实践,系统讲解如何用 Gradle C…

2026/10/14 2:22:24 阅读更多 →
从慢查询到Elasticsearch:倒排索引与分布式搜索入门避坑

从慢查询到Elasticsearch:倒排索引与分布式搜索入门避坑

第一次认真接触 Elasticsearch,不是赶新技术,而是被一条慢查询逼的。当时我在维护一个订单检索模块,数据量涨到六百多万条以后,按商品名称做模糊搜索的接口开始频繁超时。改 SQL、加索引、换缓存,折腾了一圈&#xff0…

2026/10/14 2:22:24 阅读更多 →
LVS+Keepalived+Nginx Docker负载均衡集群实战

LVS+Keepalived+Nginx Docker负载均衡集群实战

1. 项目概述:为什么一个负载均衡集群要绕这么大一圈?“基于Docker搭建lvskeepalivednginx实现高性能负载均衡集群”——这个标题里藏着三层技术栈的叠加,不是炫技,而是现实业务中反复踩坑后沉淀下来的务实选择。我最早在某高校实验…

2026/10/14 2:22:24 阅读更多 →
风电水电联合调度优化算法与工程实践

风电水电联合调度优化算法与工程实践

1. 项目背景与核心价值去年参与某省级电网清洁能源消纳项目时,我第一次接触到风-水联合调度这个课题。当时面对风电出力的强随机性和水电调节的滞后性,团队在制定优化运行方案时遇到了不少挑战。这个经历让我深刻认识到:在双碳目标下&#xf…

2026/10/14 2:21:24 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →