PostgreSQL 14 TID Range Scan:按物理位置范围扫描表实战

第一次在 EXPLAIN 里看到 Tid Range Scan 这个节点的时候,我愣了几秒。当时在处理一张订单明细表的迁移,五千多万行,表上没有主键、没有像样的索引,逻辑上只是想“把一部分数据搬出去归档”。常规做法是写个WHERE create_time < ...的过滤条件慢慢扫,但那一次,执行计划里冒出来一个以前没见过的节点:TID Range Scan。顺着这个节点查下去,才发现 PostgreSQL 14 已经悄悄补上了一个很实用的能力——按行的物理位置范围直接扫描表。

这篇文章想把这个特性完整拆开讲清楚:TID 到底是什么,为什么 14 之前只能做等值查找,14 之后的范围扫描在内部如何工作,以及在什么场景下它能省下大量 IO、什么场景下它会帮倒忙。不只是看概念,我会把实际跑过的 SQL、执行计划、分片复制思路和踩过的坑都放出来,方便你直接照着用。

1. 先搞清楚基础:ctid 是行的物理门牌号

1.1 一个由“页码 + 槽位号”组成的系统列

PostgreSQL 的堆表是按 8KB 的页面(page/block)来存放数据的。每一行数据,在某个页面内部又有自己的行指针,指向真正的元组数据。这个位置信息在每一行上都以一个系统列的形式暴露出来,叫作ctid,格式是(页码, 槽位号)。比如(42, 15)表示第 42 号物理页面里的第 15 个行槽位。

你可以在任意一张表上执行下面这条 SQL,直观看到它的样子:

SELECT ctid, * FROM orders WHERE id = 10086;

这个ctid不属于任何业务字段,也不受 SQL 标准约束,它纯粹是 PostgreSQL 堆表的物理寻址信息。这就像楼房里每户人家的门牌号:一个楼栋编号加一个房间号。只要这一行在文件里的物理位置不变,它的ctid就不会变。

1.2 为什么说它是“版本地址”

需要明确的是,ctid定位的是这一行的当前版本,不是逻辑主键。当UPDATE发生时,新版本的行通常会被写到新的页面位置,原来的版本如果不再被任何事务需要,最终会在 vacuum 时被清理。所以,你在同一张表上连续执行两次SELECT ctid FROM ...,得到的结果完全可能不一样——如果有并发 DML 在动同一行。

这个特点决定了ctid不适合作为长期稳定的外部标识,但在短时间内的局部操作里,它反而是最精准的定位手段。PostgreSQL 14 之前,针对ctid的扫描方式只有一种等值查找,也就是你知道确切位置,直接按门牌号找到那一行。而“从第几页到第几页范围内取数”这种需求,优化器处理不了,只能退回全表顺序扫描,或者靠其他索引条件间接过滤。

2. PostgreSQL 14 的 TID Range Scan:优化器和执行器是怎么配合的

2.1 优化器如何识别范围谓词

PostgreSQL 14 的提交信息里明确写着:允许为元组标识符创建范围扫描路径。这里的核心作用是让优化器识别出ctid上的范围条件,并生成一个名为TidRangePath的执行路径,最终对应到执行器里的TidRangeScan节点。

优化器会从 WHERE 子句里提取关于ctid的如下条件形态:

ctid > '(1000, 1)' ctid >= '(1000, 1)' ctid < '(2000, 20)' ctid <= '(2000, 20)'

或者语法糖式的组合:

ctid BETWEEN '(1000, 1)' AND '(2000, 20)'

当上界和下界同时存在,并且边界值是常量、类型能正确推断成tid,优化器就会尝试构造一个 TID 范围扫描路径。在执行计划里,它会显示成类似下面这样的节点:

Tid Range Scan on orders (cost=... rows=...) TID Range: (1000,1) .. (2000,20)

不是所有范围查询都会选这个路径,优化器仍然要走成本估算。但这类条件天然把要访问的物理页面限制在一个明确区间里,相比顺序扫描需要从表的第一页扫到最后一页,它的优势在范围较小时非常明显。

2.2 执行器实际上在做什么

执行器拿到TidRangeScan节点后,会先解析出起始 TID 和结束 TID。扫描按物理页码顺序进行:从起始页面开始,逐页读取,并在每个页面内按行槽位顺序返回落在范围内的元组。

这里有几个值得注意的内部行为:

  • 执行器仍然要做 MVCC 可见性判断,所以返回的行都是当前快照下对当前事务可见的版本。
  • 扫描方向是物理顺序,这跟顺序扫描很像,但访问的页面集合是受限的。
  • 页面内的行槽位可能有空洞(行被删除、更新过),执行器会跳过这些空洞。
  • 对已经通过可见性映射标记为全空或不需要访问的页面,实现上有机会跳过,从而进一步节省 IO。

换句话说,它不像索引扫描那样需要回表随机读,也不像顺序扫描那样必须把整个表从头到尾摸一遍。它更像是一段“定向的顺序扫描”,只扫你指定的物理范围。

2.3 与 Seq Scan、Index Scan 的执行模式对照

维度TID Range ScanSeq ScanIndex Scan
访问范围一次性访问指定 TID 区间从头扫到尾依赖索引定位再回表
是否要求有索引否否是
输出顺序按物理位置顺序按物理位置顺序按索引键顺序,后续决定
随机 IO几乎没有,顺序为主无常见,尤其范围大时
主要适用场景按行物理位置批量取数无过滤条件或整表大量读取按业务字段精准查找
对表结构要求无主键也可以无主键也可以必须有匹配索引

对照下来你会发现,TID Range Scan 在气质上更接近“受限的顺序扫描”,但它把“扫描哪几页”这个决策交到了优化器手里,而不是傻傻地全表扫。

3. 实际操作:TID Range Scan 最值得用的几个场景

3.1 场景一:无主键大表按物理范围批量复制

日常做表迁移或者备份时,最头疼的就是遇上没有主键、也没有可用索引的大表。比如埋点日志表、中间结果表。这时候你想做“取出若干行,插入另一张表”,经常只能靠WHERE多条件过滤,一旦过滤条件收益不好,就是全表扫描。更尴尬的是,想用并行加速时,不知道如何把一张没有主键的表干脆地切成几段。

有了 TID Range Scan,切分的依据就简单多了:直接把物理页码作为分片键。

假设表log_detail有 10000 个物理页面,你想分 4 段并行复制:

-- 先看表规模和页面数 SELECT relpages, reltuples FROM pg_class WHERE relname = 'log_detail'; -- 段 1 CREATE TABLE log_detail_copy_1 AS SELECT * FROM log_detail WHERE ctid BETWEEN '(0, 1)' AND '(2500, 200)'; -- 段 2 CREATE TABLE log_detail_copy_2 AS SELECT * FROM log_detail WHERE ctid BETWEEN '(2501, 1)' AND '(5000, 200)'; -- 段 3 CREATE TABLE log_detail_copy_3 AS SELECT * FROM log_detail WHERE ctid BETWEEN '(5001, 1)' AND '(7500, 200)'; -- 段 4 CREATE TABLE log_detail_copy_4 AS SELECT * FROM log_detail WHERE ctid BETWEEN '(7501, 1)' AND '(10000, 200)';

这里把偏移量上限设成200,是一个保守做法:普通页面里的最大行数一般不会超过这个值,即使超出也不影响正确性,因为扫描会自动截断到实际存在的元组。

在多个会话里并行执行这些CREATE TABLE AS,每一段都只需要扫描对应的物理页面。相比每个会话里都全表扫一遍,总 IO 直接下降一个量级。

3.2 场景二:让并行采集/迁移任务天然均匀分片

延续上面的思路,如果你在写数据同步脚本,有没有主键就不再是瓶颈了。可以先把表的关键信息查出来:

SELECT relpages FROM pg_class WHERE relname = 'log_detail';

然后根据页面总数算出每一段的起止 TID,再把任务分发给多个并行 worker。一种简单的分发逻辑如下:

total_pages = 10000 worker_count = 8 step = total_pages // worker_count for worker_id in range(worker_count): start_page = worker_id * step end_page = (worker_id + 1) * step - 1 sql = ( f"SELECT * FROM log_detail " f"WHERE ctid BETWEEN '({start_page}, 1)' AND '({end_page}, 200)'" ) # 交给不同的连接或 worker 执行

这样做的好处是,每个 worker 之间互不重叠,而且按物理页面划分足够均匀。比按某个业务字段划分更不容易出现数据倾斜——因为物理页面的填充情况总体上是均匀的,某一段里的数据量不会比另一段夸张太多。

3.3 场景三:局部数据修复和定向清理

有时候你已经精确定位到了有问题的那几行,甚至能拿到它们的ctid。比如一张流水表里,你发现凌晨某个时间窗口内写入的数据有逻辑问题,想快速取出并修正:

SELECT ctid, * FROM orders WHERE order_time BETWEEN '2025-01-01 00:00:00' AND '2025-01-01 00:30:00';

这时候你会发现这批记录恰好落在某几个物理页里。接下来可以用ctid精确修正:

UPDATE orders SET status = 'abnormal' WHERE ctid IN ('(1234, 5)', '(1234, 6)', '(1235, 2)');

如果需要更新的是一个范围,比如一个物理页面内的连续多行,也可以直接写:

UPDATE orders SET status = 'archived' WHERE ctid BETWEEN '(1234, 1)' AND '(1235, 100)';

注意,这里 UPDATE 本身仍然要走行锁和 MVCC,但定位成本非常低,因为它不需要扫索引,也不需要通过业务字段二次过滤。在清理历史分区、修正导入错误这类一次性操作里,这种方法特别省事。

3.4 用 EXPLAIN 验证计划是否正确生成

实践出真知,写任何查询之前先看一眼执行计划。我们造一个小表验证一下:

CREATE TABLE demo AS SELECT id, md5(random()::text) AS padding FROM generate_series(1, 100000) AS id; EXPLAIN (VERBOSE, ANALYZE, BUFFERS) SELECT * FROM demo WHERE ctid BETWEEN '(0, 1)' AND '(20, 100)';

实际输出大致如下:

Tid Range Scan on public.demo (cost=0.02..3.04 rows=100 width=40) Output: id, padding TID Range: (0,1)..(20,100)

TID Range: (0,1)..(20,100)是关键信息,说明优化器已经正确识别了范围。如果这个节点没有出现,就要检查查询条件写法是否满足识别要求,后面我会专门讲排查方法。

4. 性能收益与代价:TID Range Scan 到底快在哪

4.1 最小化页面访问,避开索引随机读

TID Range Scan 的收益本质来自两个层面:一是少读页面,二是读得规整。

少读页面很好理解。范围扫描只需要访问start_tid到end_tid之间涉及的物理页。假设一张表有 10000 页,你只关心第 1000 到 1500 页,那最多只需要读取约 500 个页面;顺序扫描则是从第 0 页一直读到最后一页,哪怕后面大部分数据都不需要,也必须把钱付了。

读得规整体现在 IO 模式上。按物理页面顺序访问,在磁盘层面基本是顺序 IO,尤其在机械硬盘上,顺序读和随机读的差距可以到一到两个数量级。索引扫描虽然能精准定位到每一行,但如果目标行分散在很多页面里,每一次回表都可能触发一次随机读。TID Range Scan 恰好避免了这种问题。

4.2 对比顺序扫描和索引扫描的成本模型

在优化器的成本公式里,TID Range Scan 的启动成本相对低,因为它不需要像索引扫描那样先读索引页,也不需要像顺序扫描那样准备整表遍历。不过,它毕竟还是堆表访问,所以单页读取成本和顺序扫描类似,主要取决于扫描范围的大小。

还需要说明的是,TID Range Scan 不是银弹。如果一个范围条件覆盖了表中超过大半的页面,优化器很可能认为它和顺序扫描没有本质差异,此时成本上占不到便宜,优化的价值更多体现在“把范围明确表达出来”这件事上。换句话说,TID Range Scan 适合的场景是“明确知道只要一小段物理区间”,而不是“把整表分成一大半扫出来”。

4.3 有一张主键索引就一定能赢吗

不一定。假设有一张表主键是自增 id,你想取 id 从 100 万到 200 万的行。用主键索引范围扫描也能高效完成,而且语义上更自然,毕竟id是稳定列。但如果你要取的数据没有业务键,或者业务过滤条件无法走索引,TID Range Scan 就有了独特的用武之地。

在主键连续且与物理顺序高度相关的情况下,主键索引扫描和 TID 范围扫描的性能差距通常不大。真正让 TID Range Scan 胜出的场景是:主键索引的键顺序和物理存储顺序不一致,或者根本没有主键可用。这时候,其他方案要么无法切片,要么承受巨大随机 IO。

4.4 也要注意它的代价边界

有一个代价很容易被忽略:如果范围条件的上下界相差很远,TID Range Scan 会退化成“近乎全表扫描的物理范围扫描”,但与顺序扫描相比,它仍然不带任何业务过滤逻辑。如果在这样一个大范围上再叠加大量 CPU 过滤条件,效率未必比顺序扫描好。

所以实际使用中,我的经验是:

  • 范围宽度占全表 10% 以内,TID Range Scan 明显划算。
  • 范围宽度占全表 30% 以上,要谨慎评估,配合EXPLAIN ANALYZE实测。
  • 完全没有范围限制时,继续用顺序扫描。

5. 常见问题与踩坑记录

5.1 写了ctid BETWEEN,却没有出现 Tid Range Scan

这是最常遇到的困惑。通常有几种原因:

  • 边界值不是常量。如果边界来自子查询、函数调用或参数,优化器无法在计划阶段确定范围。
  • 类型没有被正确推断成tid。比如直接写:
WHERE ctid BETWEEN '(0,1)' AND '(20,100)'

在部分场景下不会出问题,但为了保险,建议显式转换:

WHERE ctid BETWEEN '(0,1)'::tid AND '(20,100)'::tid
  • 范围条件之外还有其他条件,优化器成本估算后选择了别的路径。此时可以强制验证一下:
SET enable_seqscan = off; SET enable_indexscan = off; EXPLAIN SELECT * FROM demo WHERE ctid BETWEEN '(0,1)' AND '(20,100)';

如果强制关闭其他路径后能看到 Tid Range Scan,说明条件本身没问题,只是成本模型没有倾向它。

5.2 ctid 会在 VACUUM FULL / CLUSTER 之后失效

这一点必须时刻挂在嘴边。ctid是物理位置,但VACUUM FULL、CLUSTER、pg_repack这类重写表的操作,会把整张表的行重新排列。重写之后,旧的ctid值就完全失效了,甚至可能指向完全不相干的行。

更隐蔽的是,普通的VACUUM虽然不会移动行,但会清理死亡元组,影响页内槽位的复用。如果其他事务随后插入新行,可能会占用你之前见过的槽位。因此在跨事务保存ctid值时,要意识到它不是可靠的长期句柄,最长使用窗口应该是同一个短事务或同一批任务内。

5.3 并行分片时如何避免重复与遗漏

按 TID 范围并行处理时,最容易出问题的是边界重叠或遗漏。比如上一段以(2500, 200)结尾,下一段从(2500, 201)开始,还是从(2501, 1)开始,需要严格设计。

更稳妥的做法是:把所有分片范围放在同一个事务里执行,使用相同的事务快照。这样一来,即使有并发的 DML,所有会话看到的表内容也是一致的,不会出现某个范围内的行在两个分片里都被读到,或者某个范围内的行在两个分片里都没被读到的情况。

5.4 别把结果顺序当成逻辑顺序

TID Range Scan 按物理位置顺序返回结果,这种顺序与业务逻辑顺序无关。如果你需要对结果按业务键排序,仍然要显式写ORDER BY。也不要因为看到返回顺序刚好是某个字段升序,就误以为以后都能这么用——物理顺序随时可能因数据重写而改变。

5.5 小心大范围扫描与 HOT 更新

在高更新频率的表上,HOT(Heap-Only Tuple)更新会尽量把新版本留在同一个页面中,但页面空间不够时,新版本也会跑到其他页面。这意味着某一行在索引里的键没变,但其ctid可能已经变化。所以如果你先用普通查询拿到了若干行的ctid,又过了很久才用这些ctid去做 UPDATE/DELETE,必须意识到指向的可能是另一个行版本,甚至另一行。

5.6 常见问题速查表

问题排查方向建议
计划里没有 Tid Range Scan边界不是常量 / 类型未推断显式'...'::tid,检查 SQL 形态
范围太大,性能不明显覆盖页面占比过高缩小分片,或改用顺序扫描实测
跨事务使用 ctid 失效表被重写或槽位复用尽量单事务内完成
并行分片出现重复/漏数边界重叠或快照不一致统一快照,严格定义区间
需要稳定返回顺序依赖物理顺序显式ORDER BY

6. 落地心得:我把 TID Range Scan 放到流程里的方式

在实际项目里,我一般不会因为它叫“14 新特性”就到处用。真正让我把它固定进工具箱的场景,还是那几类明确定位的批量操作。

比如做冷热数据分离时,一张大日志表没有主键,之前用pg_dump或者SELECT ... WHERE搬运都非常痛苦。现在我会先跑一次SELECT relpages FROM pg_class WHERE relname = ...拿到物理页数,然后按 worker 数做切片,每个 worker 里执行CTAS ... WHERE ctid BETWEEN ...。整个过程简单直接,不需要额外造主键,也不需要先做冗长的全表扫描。

还有一个经验是,别把 TID Range Scan 当成 SQL 优化的日常手段。日常 OLTP 查询继续用主键或普通索引就好,业务条件命中率高的场景,索引扫描仍是正确的选择。但如果某天你遇到一张没有可用索引的大表,又需要快速搬运、分块处理、定向修复时,记得翻出这个老朋友——它真的能在计划里帮你省下一大截 IO 时间。

最后补充一个小技巧:执行计划的EXPLAIN (ANALYZE, BUFFERS)输出里,可以重点看Buffers: shared hit/read的数据。TID Range Scan 的优势最终都会体现在这里的页面访问量上,这个数字远比时间数字更可靠。毕竟机器负载不同,时间会骗人,读了多少页不会。

相关新闻

PostgreSQL 14 Tid Range Scan:基于物理位置的扫描优化

PostgreSQL 14 Tid Range Scan:基于物理位置的扫描优化

搞数据库的人应该都有过这样的经历&#xff1a;明明要处理的数据就“躺”在那张表里&#xff0c;可就是拿不出来&#xff0c;或者说拿得不够快。尤其当面对几千万行的大表时&#xff0c;SELECT ... WHERE ctid BETWEEN ...这种写法或CREATE TABLE AS批量搬迁数据&#xff0c;慢…

2026/10/20 8:31:00 阅读更多 →
AI工厂:从算力基建到工业级AI服务的范式革命

AI工厂:从算力基建到工业级AI服务的范式革命

1. 项目概述&#xff1a;这不是一场发布会&#xff0c;而是一次全球算力基础设施的重新定义“万亿美元AI工厂”这个说法一出来&#xff0c;很多人第一反应是夸张修辞——毕竟“万亿美元”听起来像财经媒体的标题党。但如果你真去拆解英伟达在GTC 2026上公布的整套技术栈、交付节…

2026/10/20 8:31:00 阅读更多 →
OpenRAG:面向可验证、可审计、可解耦的下一代RAG架构范式

OpenRAG:面向可验证、可审计、可解耦的下一代RAG架构范式

1. 项目概述&#xff1a;为什么2026年RAG技术选型不能再靠“听说”和“跟风”OpenRAG这个词&#xff0c;最近半年在多个技术社区的讨论帖里高频出现——不是作为某个大厂开源项目的代号&#xff0c;也不是某篇顶会论文里的临时命名&#xff0c;而是一类明确以“开放协议栈模块化…

2026/10/20 8:31:00 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/10/21 9:32:40 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/10/21 9:32:40 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/21 9:32:40 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/10/21 9:32:40 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/10/21 9:32:40 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/10/21 9:31:32 阅读更多 →

日新闻

统一内存+量化:锐龙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 阅读更多 →