压缩物化:解决OLAP执行引擎中间结果内存爆掉的实战指南
跑了一晚上TPC-H压测凌晨三点盯着监控曲线发现内存又爆了。查了一圈Profile问题根本不在扫描算子也不是Hash Join的build表而是排序之后的物化Materialization阶段把几亿行中间结果整整齐齐铺在内存里活活撑爆了配额。那段时间我都在想同一个问题能不能在物化的那一刻就把数据压起来让中间结果本身变小后来真正把压缩物化Compressed Materialization落到执行引擎里性能曲线才终于正常了。这篇东西不聊概念PPT就讲压缩物化到底怎么运转、为什么该在这个阶段压缩而不是靠存储层的列压缩兜底、以及我实际压测时踩出来的那些坑。适合正在折腾OLAP执行引擎、做向量化查询优化或者被大查询中间结果集内存占用折磨的人看。看完你能照着搭一个最小验证环境也知道怎么判断“这个Query该不该启用压缩物化”。1. 物化为什么成了查询性能的隐形瓶颈1.1 一次压测事故引出的物化问题几个月前我在调一个多表关联分析场景表结构不算复杂核心是一张十亿行的事实表和两张维表做Join。运行到某条聚合SQL时内存直接冲到配额上限容器被OOMKilled。一开始我怀疑是Hash Table太大毕竟十亿行的Join容易在这块出事。但DuckDB的EXPLAIN ANALYZE结果打出来Hash Table只占了几百MB真正的大头是Sort和Window这两个算子之间的一段物化缓冲。问题就出在Sort算子完成排序后为了给下游的Window算子提供稳定的元组流执行引擎把所有排好序的中间结果整体实体化Materialize。实体化就是拷贝一份完整、连续、未压缩的数据块写到内存或者临时文件里。这个行为听上去人畜无害但它本质上是把“数据量”原封不动地从算子A搬到算子B中间不经过任何瘦身。当中间结果集特别大时物化区就成了整个查询的内存峰值来源。我做了一个很粗糙的量化那条SQL的中间结果有差不多2.8亿行每行包含一个订单ID、三个度量字段、两个维表外键和一个时间戳行宽大概60字节。不压缩直接铺开就是 2.8亿 × 60B ≈ 16.8GB。数据还没进最终的聚合光是排队等消费就已经占掉16.8GB。这个数字在任何容器配额下都是灾难。1.2 物化不只是“临时写盘”这么简单物化在最朴素的数据库教科书里被描述成“算子输出落到存储介质供后续算子消费”。但在现代向量化执行引擎里物化远不是写个临时文件这么简单。它有几种存在形式算子间的阻塞物化Blocking MaterializationSort、Hash Aggregate这类阻塞算子必须先拿到全部输入才能产出输出于是它们把输入整体物化到内存或磁盘再开始第二阶段处理。流式物化Streaming Materialization像Hash Join的build端先把一侧所有数据包装进hash table再开始探测。构建hash table的过程本质上也是物化只是它的落点是自定义哈希结构而不是裸数据缓冲。中间结果的显式物化查询里出现子查询、CTE、窗口函数时优化器可能决定把中间结果复制一份供多个消费者使用。物化的开销来自几个方向。第一是内存占用这是最直接的机会成本内存被物化区占住留给其他算子的Buffer Pool就少了。第二是带宽数据从内存拷到另一个内存缓冲区时要走至少一次全量读写内存带宽在这种大结果集场景下倒是比磁盘I/O宽松不少但也不是无限量的。第三是缓存局部性未压缩数据块在L2/L3 Cache里的有效数据密度低下游算子扫描时缓存命中率自然不如紧凑数据。如果你停在这里想会得出一个结论要是物化阶段就能把数据体积压下去内存峰值、带宽消耗、缓存命中率这三个问题会同时缓解。这就是压缩物化的逻辑起点。1.3 压缩物化不等于存储层的列式压缩这里必须划清一条界线压缩物化Compressed Materialization发生在执行引擎内部是算子输出缓冲区的在线压缩策略存储层的列式压缩如Parquet的Snappy/ZSTD、ClickHouse的LZ4发生在磁盘文件或内存表扫描阶段。两件事经常被混为一谈实际上它们的诉求相差很大。存储层压缩面对的是静态文件可以花较多时间选择一个高压缩比的算法因为解压可以延迟到查询发生时而且一次压缩、多次复用。物化层的压缩面对的是动态中间结果它发生在查询执行的关键路径上压缩时间会计入查询延迟解压也发生在同一次查询内。换句话说存储层压缩是“文件界的一次性投资”物化压缩是“查询界的即时博弈”。你在物化阶段选择LZ4还是ZSTD本质上是拿压缩时间换内存空间或者反过来拿内存空间换压缩时间。这个trade-off必须放在整个查询的执行上下文里看不能照搬存储层的配置经验。2. 压缩物化的核心技术原理2.1 按Block/Chunk粒度整块物化是压缩物化的前提想压缩物化先得搞清楚压缩的“对象”是什么。传统tuple-at-a-time执行模型里物化缓冲是一个接一个的行元组这种结构对压缩极不友好。每行的字段类型混杂长度不一压缩算法很难找到高重复模式。现代分析型引擎普遍采用向量化执行数据在算子之间以Block或Chunk为单位传输一个Block内是若干列每列是一个包含同构数据类型元素的数组。比如一个包含1000行的Block在内存里实际上是若干个独立的列数组Column A是Int64数组Column B是Float64数组Column C是可变长字符串数组。同构列数组是压缩的理想输入。对Int64列做delta encoding效果立竿见影对字符串列做字典编码重复值越多压缩比越惊人。正是因为“物化单位”从行变成了Block我们才可以用高效的批量压缩算法去处理它。我习惯把Block物化和压缩的过程拆成三步上游算子产出一个完整Block内部列数组尚未压缩。物化器遍历这个Block的每一列用配置的压缩算法LZ4或ZSTD逐列压缩压缩后的列数据写入物化缓冲。在缓冲区头部写一个Block元数据记录每列的原始长度、压缩后长度、编码类型和行数方便后续算子解压。注意物化缓冲里不仅有压缩数据和元数据最好还留一个“偏移表”。传统物化是全量拷贝压缩物化则是“先压后存”如果下游只需要某几列偏移表能帮你跳过无关列的加载这是压缩物化额外带来的收益。2.2 压缩算法选型为什么LZ4是执行引擎默认选择压缩物化的算法选型本质上是在压缩率和压缩/解压速度之间找平衡。我用一张表记录一下我在这种场景下的实测感受。算法压缩率TPC-H lineitem柱状数据压缩速度解压速度适合物化场景吗LZ42.0x - 3.5x极快极快首选绝大多数在线物化场景ZSTDdefault level2.5x - 4.5x中等快中间结果集巨大且CPU有冗余时Snappy2.0x - 3.0x快快跟LZ4接近但生态绑定更明显Brotli3.0x - 5.0x慢较慢不适合在线执行压缩开销不可接受为什么执行引擎不能无脑上压缩率最高的算法因为查询执行是流水线每个压缩块都可能被下游算子解压一次甚至多次。如果压缩省下的内存是1GB但压缩解压让查询多跑了30秒这个代价在OLAP场景经常是负优化。LZ4的强项在于解压速度极快实测数据里LZ4解压速度通常在4-8GB/s这意味着即使Block被反复解压CPU开销也完全可控。ZSTD可以在物化结果块极大、且后续算子还要基于压缩态做某些聚合时作为备选。比如数据块从物化缓冲进入下一个Aggregate算子前可能还要经历一次GroupBy判断。如果采用ZSTD压缩时间会拖慢GroupBy拿数据的路径反而得不偿失。所以我的默认推荐是没有特殊理由就用LZ4。2.3 延迟解压与稀疏索引避免“取一行解压一整块”压缩物化遇到的第一个嘲讽是你说压缩后内存省了但下游算子拿数据的时候总得解压吧如果算子要Scan全量数据解压全部Block是合情合理的。可麻烦在于OLAP执行算子经常按行号或者按范围随机访问物化缓冲。举个例子一个Sort算子输出的物化缓冲后续被Window算子按“分区内部偏移”读取数据或者物化缓冲同时被两个消费者读取一个消费者只要前1000行另一个消费者只要特定的几个ID。如果每次读取都解压整个Block压缩物化不光没帮你省CPU反而把数据读写的复杂度增加了一个量级。解决方案是延迟解压Lazy Decompression加稀疏索引物化缓冲区里为每个Block建立行号区间索引RowId → BlockId。下游算子首次访问某个Block的特定行时只解压该Block涉及的列数组并把它挂在Block的“已解压”缓存里。如果后续几行也命中同一个Block直接使用缓存中的解压数据不再重复解压。当缓存块比例过高时执行引擎通过LRU策略释放掉最早解压的Block缓存防止解压占用跟压缩省下的空间一样多。实际工程里Block大小会直接影响延迟解压的收益。Block太小行号索引过密索引本身的元数据开销会吃掉压缩收益Block太大一次随机访问就要解压大量行延迟解压形同虚设。我配置过8192行/Block对于典型分析查询是一个相对稳妥的起点。配合LZ4绝大多数Block能在几百微秒内解压完成。关键心得压缩物化项目的核心不是“压缩”而是“如何设计一套物化缓冲让压缩数据在下游访问时依然保持随机访问能力”。这个设计一旦做好压缩物化的收益才会真正兑现。3. 实际运行分析一个可复现的压测场景3.1 实验环境与物化场景说明纸上谈兵没意思我搭了一个最小可验证的环境。实验目的是对比同一查询在“关闭压缩物化”和“启用压缩物化”两种情况下的内存峰值、执行耗时和CPU开销。实验环境CPU8核支持AVX2内存32GB引擎自研的简化向量化执行引擎支持Block物化和LZ4压缩物化数据集模拟订单流水表共3亿行维度表50万行模拟一次Hash Join Sort Window的中间结果物化场景查询逻辑大致是这样SELECT o.customer_id, SUM(o.amount) OVER (PARTITION BY o.region_id ORDER BY o.order_ts) AS running_total FROM orders o JOIN customer c ON o.customer_id c.customer_id ORDER BY o.region_id, o.order_ts;这条查询里最核心的物化点有两处Join完成后的结果集会被物化一次供Sort算子阻塞排序Sort完成后的有序结果集还会被物化一次供Window算子做分区累计。第一次物化的结果行宽约64字节规模约2.4亿行第二次物化结果规模接近2.3亿行行宽约48字节。这个规模足够暴露出内存峰值问题。3.2 两组运行对比内存、耗时与CPU开销我手动切换了两组运行方式实际跑出来的数据大致如下。指标普通物化未压缩压缩物化LZ4Join后第一次物化内存占用15.4 GB4.2 GBSort后第二次物化内存占用11.2 GB3.1 GB总查询时间26.8s19.4s物化阶段CPU时间2.7s纯拷贝5.1s含压缩下游算子读取物化缓冲耗时8.6s5.8s内存峰值附近是否触发Swap触发未触发数据很有意思。压缩物化那一组的物化阶段CPU时间确实变高了LZ4压缩不是免费的这符合预期。但总查询时间不升反降原因有两层第一内存占用降下去之后普通物化组在内存峰值附近发生了明显的Swap一些物化块被换到磁盘再换回来这比LZ4压缩的CPU开销贵多了第二下游算子读取压缩物化缓冲时数据体积小了3-4倍内存扫描和拷贝的时间大幅减少读路径的净耗时反而优于普通物化。我还单独测了一个“只读物化缓冲不做其他计算”的微基准验证上述判断对同一物化结果做全量Scan普通物化3.1GB耗时620ms压缩物化约880MB扫描时需要解压耗时410ms。解压确实有开销但压缩后数据量减小、缓存命中率高综合下来反而更快。注意如果物化缓冲区大到触发Swap普通物化几乎必输如果内存充足且物化块能完全驻留在内存里压缩物化的收益会缩小到“略快一点”但也不会是负收益。所以在OLAP引擎里默认启用LZ4压缩物化是相对安全的选择。3.3 为什么在这个场景里压缩物化能赢直接做结果归因。这个场景里压缩物化能赢主要靠三个因素叠加。第一个因素是数据本身的可压缩性。订单流水表的customer_id、region_id、amount字段都有明显的重复规律和数值范围。region_id在几十个分区内反复出现amount在固定区间内分布delta编码加LZ4后压缩比接近3.6:1。如果换成随机UUID为主键的结果集压缩率会掉到1.3:1左右这时候压缩物化的收益会大幅缩水。第二个因素是物化结果的下游消费方式。这个查询的Sort和Window算子都需要全量扫描物化缓冲Full Scan场景下延迟解压命中率高压缩数据的扫描带宽优势能充分释放。换句话说压缩物化最适合下游算子是“顺序消费”的物理计划。第三个因素是内存压力的系统性影响。说直白一点物化不是孤立环节物化区内存一旦压爆整体的Buffer Pool、操作系统的Page Cache都会遭殃触发Swap之后整个查询链条都会开始卡顿。压缩物化把内存峰值从峰值区拉回安全区间接救活了整个执行计划。如果这条SQL改成下游只随机取1000行或者物化结果列全部是高基数随机串压缩物化的结论就得重新写。这也是下一篇想展开的话题。4. 常见问题与排查笔记4.1 高基数列把压缩物化拖垮了怎么办我在实验时就专门试过一张“用户行为事件表”事件ID是UUID用户ID也是UUID设备指纹是半随机的字符串。这种列放进压缩物化LZ4的压缩率惨不忍睹常常只有1.2x-1.5x。压缩时间照付内存却只省下一点点压测数据很快变得很难看。针对这种情况我的处理办法是列级自适应压缩。物化器在压缩Block的前一刻先对每列做快速基数采样。采样结果如果显示这一列基数极高、值分布接近随机就跳过压缩直接按原始数据写入物化缓冲只有低基数、可预测的列才走LZ4。这个逻辑实现起来不复杂本质上就是在压缩循环里加一个基于样本的判断函数。我在实际项目里是这样实现的def should_compress_column(col_meta, sample_ratio0.05): sampled col_meta.sample(int(len(col_meta.data) * sample_ratio)) distinct_ratio len(set(sampled)) / len(sampled) # 超过这个阈值就认为该列不适合压缩 return distinct_ratio 0.8阈值0.8不是拍脑袋是我对几组数据实测后的经验值。低于0.8时LZ4通常能拿到1.8x以上的压缩率高于0.8时压缩收益太小直接放弃更划算。这个自适应逻辑加进去之后混有大量随机列的场景总耗时又降了约8%内存节省依然保持在2.5x以上。4.2 随机访问导致反复解压性能反而倒退了还有一个翻车场景是有一次把窗口函数的物化结果作为维表在探测阶段按行号随机访问。当时没配延迟解压和LRU缓存导致每次随机取一行都解压整个BlockCPU时间直接翻了三倍查询跑得比普通物化还慢。这个问题的解法分两步。第一物化缓冲的Block元数据一定要支持“该Block当前是否已解压”的状态位每个Block最多解压一次解压后的列数组放进缓存重复访问直接命中。第二缓存不能无限制膨胀我用一个简单的LRU List管理Block解压缓存缓存上限设为物化总大小的20%。超过上限就按访问时间淘汰最旧Block。配置好之后我把随机访问场景重新压测了一遍查询耗时从“普通物化的1.4倍”变成“普通物化的0.9倍”虽然收益不像Full Scan场景那么夸张但至少不再倒退了。这件事给我的教训是压缩物化的收益模型跟访问模式强相关做工程之前先画出下游算子的数据访问模式图别把Full Scan的乐观结论套在随机访问场景上。4.3 压缩物化和存储压缩叠加存在双重压缩风险最隐蔽的问题来自“File Scan阶段已经用ZSTD压缩了页面物化阶段再用LZ4压缩一遍”。如果数据从存储层进入执行引擎时已经是以压缩页加载的执行引擎扫描完页面生成Block时数据是解压后的原生状态。这时候做物化压缩是合理的因为数据已经脱离了文件压缩的保护范围。但有些引擎在Scan节点和物化节点之间会有页缓存Page Cache层页缓存里的数据可能还是文件压缩态。如果物化器不加判断直接把未解压的页数据又套一层压缩等下游算子使用时再解压两层CPU白白多烧一遍。解决办法是在物化器入口检查数据状态标记。我习惯在Block的元数据里加一个字段is_from_compressed_page。Scan节点物化出来但未解压的Block直接原样透传到物化缓冲区禁止重复压缩。这个检查在代码里就是多一行判断但能避免非常隐蔽的CPU浪费。4.4 几个调参建议避免“越优化越慢”压缩物化的参数陷阱很多这里整理几个我常用的经验值供参考。Block行数默认8192行。如果物化结果的行宽很大超过256字节可以降到4096避免单个Block解压时放大延迟如果行宽很小32字节以内提到16384更合适。压缩算法切换阈值物化数据量大于512MB时使用ZSTD小于512MB时用LZ4。小数据量下ZSTD的压缩时间占比太高完全没有必要。解压缓存上限设为物化缓冲总内存的20%左右太小会频繁触发解压和淘汰太大又抵消了压缩节省的空间。压缩线程数如果物化区是多线程并行的压缩线程数建议等于物理核数的一半不要占满全部CPU核。物化压缩不是查询的主要计算瓶颈留出核给下游算子更关键。最终心得压缩物化不是银弹它最擅长的是“大中间结果集 顺序消费 数据有可压缩性”这个三角形场景。一旦三角形缺了一角就得靠自适应压缩和延迟解压这些补充机制去兜。我现在的习惯是跑任何一条大查询前先看EXPLAIN ANALYZE里的物化部分判断Block体积和访问模式再决定要不要在物化节点铺压缩策略。每次调压缩物化的参数我都会想到最开始那个凌晨。真正让我觉得这套机制值得做的不只是内存曲线平稳了而是同一套执行引擎在应对中间结果集“膨胀”时的弹性明显好了。后续如果接着折腾我会把压缩物化从LZ4扩展到ZSTD的分级联合压缩再把它接入到lookup join场景里做一块“按列延迟物化”的实验。毕竟数据库执行引擎的乐趣就在于你永远能找到下一个让人半夜爬起来看一眼监控曲线的地方。

相关新闻

JSP+Servlet笔记系统:细粒度权限控制与反编译重构实战

JSP+Servlet笔记系统:细粒度权限控制与反编译重构实战

简介:这是一份面向Java初学者与毕业设计学生的JSP Web应用实战项目资源,完整实现了一个具备用户管理、标签检索、笔记公开与权限控制的共享笔记系统。系统核心包含文本共享数据存储模块,通过细粒度权限机制保障笔记访问安全,并与用…

2026/10/9 10:47:22 阅读更多 →
Linux共享内存全解析:零拷贝、mmap与信号量实战

Linux共享内存全解析:零拷贝、mmap与信号量实战

搞Linux后台开发这些年,凡是跟高并发、低延迟沾边的系统,最后几乎都会绕到共享内存这扇门面前。管道传小数据还行,真到几十MB的日志、上百万条结构化消息,一次一次往内核里拷贝数据,延迟和CPU都受不了。共享内存就是把…

2026/10/9 10:47:22 阅读更多 →
AI漫剧生产管线全拆解:角色一致性、资产库与废片率控制实战

AI漫剧生产管线全拆解:角色一致性、资产库与废片率控制实战

AI漫剧这个方向,我从去年下半年开始断断续续折腾了大半年,从最开始用单张图加配音拼PPT式的“伪漫剧”,到后来能稳定日产3到5集、废片率压到15%以内,中间踩的坑实在太多了。今天不聊虚的,就把我这套从零搭起来的AI漫剧…

2026/10/9 10:46:21 阅读更多 →

最新新闻

Codex 额度重置后,开发者如何用 TaoToken 统一管理 API 调用?

Codex 额度重置后,开发者如何用 TaoToken 统一管理 API 调用?

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

2026/10/9 11:17:09 阅读更多 →
t3code 多AI编程工具统一调度:Electron本地代理与配置切换实战

t3code 多AI编程工具统一调度:Electron本地代理与配置切换实战

1. 从"t3code"这个名字说起:它到底想解决什么问题第一次看到"t3code"这个项目名,我脑子里冒出来的第一个念头是:这大概率又是一个把当下几款主流 AI 编程工具串起来的中间层工具。事实也确实如此。从围绕它的热搜词能看出…

2026/10/9 11:17:09 阅读更多 →
t3code 全栈开发实战:Next.js + tRPC + Prisma 类型安全指南

t3code 全栈开发实战:Next.js + tRPC + Prisma 类型安全指南

1. 从“t3code”这个标题说起:它到底是什么 第一次看到“t3code”这个词,我脑子里蹦出来的第一反应是——这大概率是个技术圈的缩写或者代号,而不是某个大众消费品。事实也确实如此。在开发者社区里,t3code 通常指的是一类围绕“T…

2026/10/9 11:17:09 阅读更多 →
Cline 3.1 版本发布后,如何用 TaoToken 统一 Key 接入 VS Code 编程助手

Cline 3.1 版本发布后,如何用 TaoToken 统一 Key 接入 VS 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/9 11:17:09 阅读更多 →
OpenMontage:用Agentic AI把视频剪辑变成可编程工程

OpenMontage:用Agentic AI把视频剪辑变成可编程工程

1. 从“剪辑苦力”到“AI导演”:OpenMontage 到底想解决什么问题做视频的人都有一个共同的痛:剪辑这件事,创意只占两成,剩下八成全是体力活。找素材、对时间轴、卡节奏点、加转场、调色、配字幕、导出不同平台的版本……一套流程走…

2026/10/9 11:17:09 阅读更多 →
操作系统期末复习重点:进程管理、PV操作与计算题全攻略

操作系统期末复习重点:进程管理、PV操作与计算题全攻略

学期末最让人头疼的,往往就是操作系统这种既像文科又像理科的课。你说它难吧,概念翻来覆去就那些;你说它简单吧,一到计算题和PV操作题就卡壳。我翻了不少“计算机操作系统考试知识点及重点总结”资料,又结合自己当年复…

2026/10/9 11:16:08 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/8 15:26: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/9 6:17:20 阅读更多 →