PDO fetchAll内存占用真相:从缓冲查询到流式处理

PDO的fetchAll(PDO::FETCH_ASSOC)是全量数据放内存了吗?这个问题我在排查线上接口内存溢出时被问过很多次。答案其实很直接:是,它会一次性把查询到的所有结果行加载到PHP内存中,返回给你一个完整的二维数组。但如果你以为“那我把查询改成分页就万事大吉”,那又忽略了PDO执行机制里真正关键的缓冲行为。这篇文章我会把背后的内存模型、服务端与客户端的读取协议、以及大数据量下真正可行的处理方案一次讲透,最后再附上我自己踩过的坑。

1. 理解全量加载的真相:不是玄学,是PDO的设计

1.1 先看fetchAll的本质:一次取完还是分批取?

fetchAll(PDO::FETCH_ASSOC)从名字上就说明了行为:把当前结果集中所有剩余的行一次性取出,组成一个数组。它等价于你手动写一个while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {}循环不断调用fetch(),然后再手动把所有行累积到数组里。区别只是fetchAll把这个累积过程封装好了。

关键在于,底层数据从数据库服务器传输到PHP进程的方式,决定了这个数组的“膨胀”速度和边界。PDO默认情况下,尤其是MySQL驱动,会启用缓冲查询(buffered query)。所谓缓冲查询,是指在执行execute()时,MySQL服务器把结果集完整发送到PHP客户端,PHP扩展把这整包数据暂存在内存里,行成一个内部的“结果缓冲区”。之后fetch()或fetchAll()只是从这个缓冲区里逐行取数据。

所以fetchAll并不是“边查边取内存”,它对内存的占用分为两层:

  1. 扩展内部的结果缓冲区:用于承接MySQL服务器发来的原始结果集数据。
  2. PHP用户空间的数组:fetchAll(PDO::FETCH_ASSOC)把每条记录解析成关联数组,再放进外层数组,这个数组就是你自己在代码里能操作的$rows。

两层内存叠加,数据量一大,内存就上去了。

1.2 从一条SQL到内存翻倍:看看实际上发生了什么

我用一个简单的例子说明。假设你有一张用户表,里面有10万条记录,每条记录平均2KB大小。

$stmt = $pdo->query("SELECT * FROM users"); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

你可能会想:10万条 × 2KB,也就是约200MB,对吧?错。实际占用通常远大于这个理论值。原因在于PHP数组的结构和字符串的内存打包方式。

每一条记录在PHP中是一个关联数组,而每个关联数组都是有哈希表结构的。哈希表不仅存键值,还会存哈希数、内部链表指针、类型标记等元信息。举例说,一条记录有10个字段,每个字段是一个字符串变量,即使字段内容很小,单个zend_string结构也需要额外的头信息。在PHP 7以上的版本,小字符串依然有额外的内存开销,只不过相对PHP 5优化了很多。实测中,10万行 × 10字段的记录集,在PHP 8环境里占用轻松超过500MB,比磁盘上的原始大小高出2到3倍。

也就是说,你不能用“MySQL查询结果的实际字节数”去预估PHP内存,必须预留宽松的余量。我自己遇到过的一个典型场景:

某后台管理系统导出报表,查询近一年的订单明细,大约30万行。直接fetchAll,配合前面的分页处理后意外地发现PHP进程内存占用超过了1GB,服务器配置的memory_limit = 512M,当场白屏。

这就是全量加载的代价:不只是SQL查询本身重,PHP这层的内存翻倍更致命。

1.3 全量加载在什么场景下会踩雷?

如果你的所有查询都只涉及几十行、几百行,fetchAll完全没有问题,我用它处理小数据量时甚至觉得比逐行fetch更清爽。但有几个典型场景特别容易踩雷:

  • 数据导出功能,查询量动辄几十万上百万行。
  • 定时任务里的批量对账、批量同步,需要一次读全量再做计算。
  • 报表聚合后返回给前端接口,结果集本身虽然不大,但单行超大,比如存储了JSON文本或日志原文字段。
  • 联表查询没加条件,意外产出了笛卡尔积类型的大结果集。

在这些场景里,fetchAll已经不是“优化与否”的问题,而是“根本不能这么写”的问题。

2. 缓冲查询与流式查询:真正决定内存大小的底层开关

2.1 PDO默认使用了缓冲查询吗?

针对MySQL数据库,PDO默认启用缓冲查询,除非你在连接DSN中明确关闭。对应的常量是PDO::MYSQL_ATTR_USE_BUFFERED_QUERY。当它默认为true时,MySQL Native Driver会在execute()阶段把整个结果集拉回客户端内存。

$pdo = new PDO( "mysql:host=127.0.0.1;dbname=test;charset=utf8mb4", "user", "pass", [ PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false, ] );

设置为false后,PDO会切换到非缓冲查询(unbuffered query),即流式模式。此时执行execute()后,MySQL服务器并没有把所有数据通过一次包体发给PHP,而是保留在服务端结果集中,PHP每次调用$stmt->fetch()才会从服务端取一行数据。此时如果你在客户端用fetchAll(),反而会变成“逐行从服务端拖取并累积到PHP数组”,内存占用虽然主要体现在用户数组这一层,但扩展内层的结果缓冲区消失了。对于不需要把所有行都保存在数组里的场景,这就是优化内存的入口。

很多人会问:那我把MYSQL_ATTR_USE_BUFFERED_QUERY设为false后,再配合fetch()一行处理一行,是不是就彻底解决了内存问题?

答案基本是肯定的,但流式查询有它的适用条件和陷阱,我放在第4节详说。

2.2 为什么说“默认缓冲”其实是数据库驱动的普遍策略?

不仅是PDO,mysqli默认情况下默认也是缓冲查询。这是出于简单和安全的考虑:一旦查询结果全部到达客户端,连接就可以立即被释放,其他SQL语句可以立刻复用该连接。而非缓冲模式下,如果你在处理结果集的过程中还想在同一连接上执行另一条SQL,就会产生冲突。数据库驱动宁可让开发者无感知地承受内存开销,也不愿让业务逻辑在“连接占用中”产生异常。

这给你带来的启示是:如果只是查询少量数据,别去动缓冲开关,默认行为更省心。只有当你确认结果集会很大,且处理逻辑是逐行流式消费时,才值得考虑关闭缓冲。

2.3 数据库原生层的“全量拉取”与PHP侧两步延迟

还有一个容易混淆的点:默认缓冲下,fetchAll真正耗时最重的是哪个阶段?

很多人以为是fetchAll()这个函数本身慢。实际上,在MySQL Native Driver + 默认缓冲模式下,数据在execute()阶段就已经全部从服务器拉取到客户端了。fetchAll()只是在内存缓冲区里做一个“搬运工”,把内部结果集翻译成PHP数组。你用微小的时间差是感受不到的,但用性能分析工具看到耗时会发现,execute()的耗时里已经包含了网络传输和等待服务端发送全部结果的时间。

反过来,非缓冲模式下,execute()非常快,真正的耗时发生在你一次次fetch()的过程中,网络I/O被切分成多次小往返。

3. 大数据量场景的正确打开方式:从fetchAll到逐行处理

3.1 最基础的替代方案:while循环加fetch()

当你的目标是“处理每一个结果行”,而不是“把结果集保存在内存里反复使用”时,逐行fetch()的组合是内存最优解。

$stmt = $pdo->prepare("SELECT * FROM big_table"); // 假设已非缓冲模式 $stmt->execute(); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { // 处理一行,这一行处理完就可以丢弃 }

在非缓冲模式下,这种写法不会把整个结果集塞进PHP内存,内存占用基本稳定在单行数据大小附近。但在默认缓冲模式下,即使写while + fetch(),由于数据在execute()阶段已经全部进了扩展内部缓冲区,实际内存占用也不会少。这就涉及一个容易被忽视的结论:

只要连接参数保持默认缓冲,无论你用fetch()还是fetchAll(),内存大头在execute()时就已经被锁定了。真正想要节省内存,第一步不是换API,而是切换为非缓冲模式。

3.2 生成器语法:把处理逻辑封装得更优雅

如果你觉得while循环太“裸”,可以用生成器把逐行读取封装成一个可迭代接口,调用方就像使用普通数组一样使用它。

function rowsGenerator(PDOStatement $stmt): Generator { $stmt->execute(); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { yield $row; } } // 使用 $stmt = $pdo->query("SELECT * FROM big_table"); // 需先确保非缓冲模式 foreach (rowsGenerator($stmt) as $row) { // 处理单行 }

生成器最大的好处是延迟执行:foreach每请求一行,生成器内部才去执行一次fetch(),这和你自己写while循环在内存表现上基本一致,但代码结构更接近“集合处理”的语义,适合在业务代码中反复使用。

3.3 数据库端分页:最稳但最容易被低估代价的方案

对流式查询有顾虑时,很多人会考虑LIMIT/OFFSET分页。这确实能限制单次查询返回的数据量。

$page = 1; $pageSize = 10000; while (true) { $offset = ($page - 1) * $pageSize; $stmt = $pdo->prepare("SELECT * FROM big_table ORDER BY id LIMIT :limit OFFSET :offset"); $stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT); $stmt->bindValue(':offset', $offset, PDO::PARAM_INT); $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); if (!$rows) { break; } foreach ($rows as $row) { // 处理 } $page++; }

这种方案的坑在于:当OFFSET非常大时,数据库依然需要扫描并丢弃前面所有行,越到后面查询越慢。相比之下,基于主键或唯一索引的“游标分页”更高效:

$lastId = 0; while (true) { $stmt = $pdo->prepare("SELECT * FROM big_table WHERE id > :lastId ORDER BY id LIMIT 10000"); $stmt->execute([':lastId' => $lastId]); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); if (!$rows) { break; } foreach ($rows as $row) { // 处理 } $lastId = end($rows)['id']; }

游标分页每次查询都从上次的最后一条ID继续往后走,走索引效率极高,而且永远不会有OFFSET越深越慢的问题。

3.4 什么情况下仍然可以安心用fetchAll?

不是所有地方都要躲着fetchAll。以下场景用它是合理且推荐的做法:

  • 结果集规模明确且很小,比如按主键查询单条记录、按唯一索引查询某个用户。
  • 需要将一个结果集整体传递给某个函数处理,比如模板渲染、数组映射、数据导出时数据已经在分页限制范围内。
  • 配合LIMIT 100这类小批次查询使用,无论怎么折腾都不会内存爆炸。

按我的实践经验,判断标准可以简化成一句话:单次结果集超过内存上限的十分之一,或者单表数据量可能超过万行且你没有明确LIMIT时,就别用fetchAll了。

4. 常见问题与排查经验实录

4.1 非缓冲模式下“连接被占用”的坑

有位同事在公司内部的数据同步任务里关闭了缓冲模式,结果遇到了一个非常诡异的报错:

SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you can use PDO::MYSQL_ATTR_USE_BUFFERED_QUERY.

这个错误的本质是:你在非缓冲模式下执行了一条查询,但还没把结果集取完,就试图在同一个PDO连接上执行另一条SQL。此时MySQL连接正处于“正在传输上一批结果”的状态,不允许插入新操作。

解决办法有三种:

  1. 在处理完整个结果集之前,不要在同一连接上执行其他SQL。
  2. 在跳出循环前,主动把剩下的结果消费掉或直接关闭Statement。
  3. 如果业务上无法避免交叉查询,就把非缓冲查询放到另一条独立的PDO连接上。

我在实际开发中更倾向做法3,因为业务代码里经常需要在逐行处理数据的同时做关联查询,比如读一条订单,再去查一下商品明细。这时候一个连接负责流式读取,另一个连接负责辅助查询,互不干扰。

4.2 不是所有驱动都支持非缓冲查询

非缓冲模式是MySQL Native Driver的特征。如果你用的是SQLite、PostgreSQL、SQL Server等其他数据库驱动,PDO::MYSQL_ATTR_USE_BUFFERED_QUERY这个常量根本不存在,同样,在那些驱动上fetchAll的行为也各有差异。SQLite并没有独立的服务器进程,数据文件由SQLite引擎直接管理,查询时数据本来就是从本地文件中逐行读出的,它内部也有自己的缓存策略,但对PHP层来说,fetchAll依然会生成一个完整数组。

所以别把“MySQL非缓冲模式”当成全数据库通用的救命稻草。在PostgreSQL下,PDO使用的是另一套游标机制,如果你有流式读取需求,得用beginTransaction()配合游标或使用驱动特定的处理方式。我上周还帮另一位朋友排查过,他在PostgreSQL下照搬MySQL那套关闭缓冲的DSN参数,结果PDO直接抛出“unknown option”错误。

4.3memory_limit是否可以通过调大来解决?

调大memory_limit是应急手段,不是根治方案。我曾经在一个老项目里看到有人为了跑导出任务,把memory_limit从128M一直加到2G。任务不崩了,但服务器上每个PHP-FPM进程都占用近2G内存,几个并发导出请求直接拖垮整台机器。

正确的思路是用前面提到的流式处理、分页或者生成器,把内存峰值压在可控范围。假如某次任务确实需要同时维护一大堆聚合数据到内存里,那就要评估是否可以把聚合逻辑下推到SQL,让数据库先做完轻量计算,再传回很小的结果集。

另外一个容易忽略的点是,memory_get_peak_usage(true)可以很方便地实时监测脚本内存峰值。我通常会在导出类脚本的关键阶段输出这个值,这样就可以确定到底是哪一步在膨胀。

4.4 使用fetchAll时返回的字段名大小写问题

最后说一个非常隐蔽的小问题。FETCH_ASSOC返回的数组键名和数据库字段名大小写相关,但这个相关规则受PDO和MySQL驱动影响。有的版本的MySQL字段定义是混合大小写,而查询时使用了驼峰别名或不同的大小写格式,fetchAll返回后,你循环时用$row['UserName']取值却取不到,因为实际键名是小写开头的。

这个问题严格说不算内存问题,但排查过程非常折磨人。建议在写SQL时统一给字段起别名,并且和PHP端取值的大小写保持一致,避免依赖驱动默认行为。这也是我把这个问题放在最后一节提醒你的原因,小事最容易在关键时刻绊一脚。

5. 实战复盘:把数据导出从内存崩溃改到稳定运行

5.1 原始代码的问题剖析

之前某个模拟项目X中,数据导出模块最初是这样写的:

$stmt = $pdo->query("SELECT * FROM operation_logs WHERE create_time BETWEEN ..."); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($rows as $row) { // 写CSV }

operation_logs表当时已经积累了上百万条记录,即使加了时间范围筛选,一次仍然可能查出几十万行。线上任务每次跑到一半,PHP就报“Allowed memory size exhausted”,然后整个导出流程崩溃。

当时的调试过程是这样的:我用memory_get_peak_usage(true)打印整个脚本的峰值内存,发现从一开始执行SQL到fetchAll这一行结束,内存直接飙升到700MB,后续写CSV反而只增加了一点点。这说明性能瓶颈完全在PHP侧的结果集缓存上。

5.2 重构方案把峰值降了一个数量级

最终我重构成了这样:

// 独立的导出专用连接 $exportPdo = new PDO( "mysql:host=127.0.0.1;dbname=project_x;charset=utf8mb4", "user", "pass", [ PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false, ] ); $stmt = $exportPdo->query("SELECT * FROM operation_logs WHERE create_time BETWEEN ..."); $fp = fopen('php://output', 'w'); fputcsv($fp, ['id', 'user_id', 'action', 'create_time']); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { fputcsv($fp, [ $row['id'], $row['user_id'], $row['action'], $row['create_time'], ]); // 注意:这里不再往积累数组里放任何数据 } fclose($fp);

重构后的耗时比之前增加了,因为不再是一次性大块网络传输,而是一行一行来回拉取,但脚本峰值内存降到了十几MB水平,服务器压力大大降低,任务也再没有因为内存崩过。

后来我又尝试了把每批5000行攒在一起fetchAll一次,再写文件,这样在网络往返次数和内存占用之间取了个平衡。相比单行fetch,吞吐量提升明显,实际项目中我认为这种“分批处理”既优雅又高效:

while (true) { $rows = []; for ($i = 0; $i < 5000; $i++) { $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!$row) { break 2; } $rows[] = $row; } foreach ($rows as $row) { fputcsv($fp, $row); } }

5.3 别忘了顺手限制导出数据的合理性

重构过程中还有一个业务层的思考:真的有必要一次导出几十万行吗?很多时候业务方只是想要最近一周的数据。后来我把默认导出范围改成了最近7天,并支持自定义时间范围但默认限制最大行数。数据量变小后,即使某些场景还是用了fetchAll,内存都在安全水位。技术优化和产品约束双管齐下,才是真正稳定的方案。

6. 写在最后的两个实用小建议

讲到这里,关于“PDO的fetchAll(PDO::FETCH_ASSOC)是不是全量数据放内存”这个问题,你应该有了自己的答案:它会,而且在默认MySQL驱动下,连缓冲查询带来的扩展内部缓存也要一起算进内存。

我个人在实际操作中的体会是,在动手改代码前先问自己三个问题:数据量明确吗?处理逻辑能流式消费吗?数据库连接能否独立拆分?这三个问题想清楚了,方案基本就出来了。流式查询加独立连接是处理大结果集的最通用组合,而小结果集完全没必要折腾,保持fetchAll最清爽。

最后再分享一个小技巧:不管用哪种方案,在PHP脚本里加上register_shutdown_function,记录一下每次任务结束后的memory_get_peak_usage(true),长期观察这些指标,比临时排查内存爆炸更有效。等你能对“这条SQL大概占多少内存”建立直觉的时候,就算真正吃透这个话题了。

相关新闻

从遥控到自主:为全向机器人lingbot打造激光雷达地图导航模块

从遥控到自主:为全向机器人lingbot打造激光雷达地图导航模块

先交代背景&#xff1a;我手上一直维护着一个开源的轻量级机器人项目&#xff0c;代号 lingbot&#xff0c;底盘是多轮独立驱动的全向平台&#xff0c;原本只能靠里程计和几个红外传感器做简单的巡线、避障。跑了一段时间之后&#xff0c;功能演示时总要跟在机器人后面用手柄遥…

2026/10/21 6:13:30 阅读更多 →
Kubernetes Job与CronJob实战:一次性任务与定时任务调度全解析

Kubernetes Job与CronJob实战:一次性任务与定时任务调度全解析

《零基础通关 Kubernetes》系列写到第9章&#xff0c;前面聊了 Pod、Deployment、Service 这些常驻服务&#xff0c;今天专门聊聊两类"跑完就走"和"到点就跑"的工作负载&#xff1a;Job和CronJob。不少朋友刚接触 K8s 时都会有这个疑问&#xff1a;我有个一…

2026/10/21 6:13:30 阅读更多 →
OOA鱼鹰算法+Transformer-BiLSTM多特征分类预测Matlab实现

OOA鱼鹰算法+Transformer-BiLSTM多特征分类预测Matlab实现

搜分类预测方案的时候&#xff0c;如果你最近翻过2023年之后的方法类文章&#xff0c;大概率会碰见"某某优化算法TransformerBiLSTM"这种三件套。第一反应多半是&#xff1a;又来一个缝合怪。说实话&#xff0c;不少论文里确实是为了凑指标才缝的&#xff0c;但基于鱼…

2026/10/21 6:13:30 阅读更多 →

最新新闻

后仿真中的race问题:三类典型场景与五步定位法

后仿真中的race问题:三类典型场景与五步定位法

干后仿仿真时间长了&#xff0c;我最怕的不是功能跑挂&#xff0c;而是那种“功能仿真全绿、门级仿真一开就莫名出现X”的情况。这类问题里&#xff0c;race-condition占了相当大一部分。前两篇讲了一些常见场景&#xff0c;这篇继续补充三个我实际遇到过、而且定位过程比较有代…

2026/10/21 7:38:02 阅读更多 →
STM32F103内部Flash读写:免外部EEPROM,实现掉电数据保存

STM32F103内部Flash读写:免外部EEPROM,实现掉电数据保存

简介&#xff1a;面向STM32F103嵌入式开发者的内部Flash读写资料包&#xff0c;覆盖Flash存储器原理、读取操作、扇区擦除、写入时序与EEPROM模拟方法&#xff0c;帮助解决程序代码存储、配置数据保存及非易失性数据读写等实用问题。资源包共156个文件&#xff0c;以C源码和头文…

2026/10/21 7:38:02 阅读更多 →
杰理AC696N开发板Windows开发环境搭建完整指南

杰理AC696N开发板Windows开发环境搭建完整指南

很多人拿到一块新开发板&#xff0c;第一反应都是先插USB、找资料、装IDE。我拿到AC6966B开发板的时候也差不多&#xff0c;但实际走了一遍才发现&#xff0c;这套AC696N开发环境并不是一个安装包能搞定的&#xff0c;它由固件工程、编译工具链、下载工具和调试串口四部分拼装而…

2026/10/21 7:38:02 阅读更多 →
私域流量自动化运营系统架构与实操:事件驱动规则引擎

私域流量自动化运营系统架构与实操:事件驱动规则引擎

1. 私域自动化运营的底层逻辑与方案选型1.1 为什么私域运营必须走自动化路线做私域的人都有一个共同的痛&#xff1a;手动运营的天花板来得特别快。一个人管三五个群还能应付&#xff0c;一旦群数量上到二十个、三十个&#xff0c;每天光是欢迎新成员、发公告、回答重复问题就能…

2026/10/21 7:38:02 阅读更多 →
MySQL生产环境压测实战:用sysbench提前暴露上线隐患

MySQL生产环境压测实战:用sysbench提前暴露上线隐患

接手过几套生产 MySQL 之后&#xff0c;我越发觉得&#xff1a;sysbench 压测这件事&#xff0c;不是跑个命令把 TPS 截图发群里就算干完了。它最大的价值&#xff0c;是在新库上线前、或者一次大的参数调整之后&#xff0c;用一套标准化的负载提前暴露那些“平时看着没事、一上…

2026/10/21 7:38:02 阅读更多 →
扫地机器人控制端开发实战:通信、地图与任务调度全解析

扫地机器人控制端开发实战:通信、地图与任务调度全解析

我最早做扫地机器人控制端的时候&#xff0c;以为就是给机器人套个App界面、加几个按钮的事。真上手才发现&#xff0c;这玩意儿远比"远程开个机、设个定时"复杂得多——你要处理的不是一条指令&#xff0c;而是一整套状态流&#xff1a;传感器数据怎么上得来、地图怎…

2026/10/21 7:37:01 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事&#xff1a;AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里&#xff0c;按宣传口径&#xff0c;本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”&#xff0c;而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起&#xff1a;用户到底在追求什么“封号重开”这四个字&#xff0c;放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流&#xff0c;背后是大量的时间和精力成本。正常情况下&#xff0c;没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”&#xff0c;而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时&#xff0c;就意识到&#xff1a;单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →