ClickHouse物化视图实战:原理、优化与避坑指南
1. 项目概述为什么ClickHouse的物化视图值得你花时间如果你正在用Clickhouse处理海量数据尤其是那些需要实时聚合、预计算报表的场景大概率已经感受到了直接查询原始明细表的“痛苦”——每次跑个简单的SUM或COUNT都要扫描数亿行查询慢得像蜗牛还拖垮整个集群。这时候一个被很多人听过但未必真正用明白的特性就该登场了物化视图。简单来说ClickHouse的物化视图就是一个“预计算”的触发器。它像一个不知疲倦的助手在后台默默盯着你指定的源表每当有数据写入时就立刻按照你预先定义好的聚合逻辑比如按天、按用户分组求和把计算结果存到另一张实际的物理表中。下次你再需要看这个聚合结果时直接查询这张结果表就行了速度能提升几个数量级。这听起来和很多数据库的物化视图概念类似但ClickHouse的实现有其独特之处用好了是神器用错了可能就是性能“黑洞”。我见过不少团队一听说物化视图能加速查询就迫不及待地创建了好几个结果发现数据写入变慢了、存储空间暴涨、甚至出现数据不一致的诡异问题。归根结底是没有理解ClickHouse物化视图的“触发器”本质和它背后与存储引擎的紧密耦合。这篇文章我就结合自己踩过的坑和实战经验带你彻底搞懂ClickHouse物化视图。无论你是刚接触ClickHouse的新手还是已经用它处理PB级数据的老兵相信都能找到对你有用的细节和避坑指南。2. 核心设计思路它到底是怎么工作的要正确使用ClickHouse的物化视图第一步必须是理解它的核心工作机制。很多人把它类比为其他数据库如Oracle、PostgreSQL的物化视图这其实是个容易误导的起点。ClickHouse的物化视图更像一个依附于源表的、自动执行的INSERT触发器。2.1 与源表的“寄生”关系当你执行CREATE MATERIALIZED VIEW mv_name TO target_table ...语句时你并不是创建了一个独立的“视图对象”。你实际上是定义了一个规则每当有数据块data part成功插入到源表source table后就立刻对这个新插入的数据块执行一次物化视图SELECT查询并将查询结果写入到目标表target_table。这里有几个关键点需要刻在脑子里历史数据不处理物化视图只对创建之后新写入的数据生效。创建之前源表中的历史数据物化视图是不会去处理的。如果你需要全量历史数据的聚合必须手动初始化。基于数据块触发触发计算的最小单位是数据块part而不是单行。这意味着物化视图的计算是批量的效率很高但也意味着在数据块合并merge过程中可能会有重复计算的风险后面会详细讲。目标表必须提前存在在ClickHouse中物化视图的存储需要依赖一张实际存在的表即TO target_table指定的表。这张表通常使用MergeTree系列引擎如SummingMergeTree、AggregatingMergeTree其表结构必须与物化视图SELECT语句的输出结果完全匹配。这种设计带来的最大好处是极低的延迟。数据一旦写入源表聚合结果几乎同步取决于计算复杂度就出现在目标表中非常适合实时监控和仪表盘。但缺点也很明显它增加了写入链路的负担因为每一批数据写入都要触发一次额外的计算和写入。2.2 存储引擎的黄金搭档SummingMergeTree与AggregatingMergeTree既然物化视图的结果需要存到一张物理表那么选择什么样的表引擎就至关重要了。直接使用普通的MergeTree往往不是最佳选择因为聚合数据可能随着源表数据的不断写入而出现多份“中间状态”数据块直接查询需要再次聚合。ClickHouse提供了专门为这种场景优化的引擎SummingMergeTree这是最常用的搭档。它会在后台合并数据块时对指定为聚合维度ORDER BY键以外的所有数值列进行求和。这样即使目标表中有多个包含相同维度键的数据块最终查询时也能通过FINAL关键字或依靠后台合并得到正确的求和结果。它适用于SUM、COUNT这类简单聚合。AggregatingMergeTree功能更强大用于处理更复杂的聚合状态如去重计数uniq、均值avgState、分位数quantilesState等。它需要配合AggregateFunction数据类型使用能够存储聚合的中间状态并在合并时正确更新。注意选择正确的存储引擎并理解其合并语义是保证物化视图查询结果准确性的基础。直接查询一个SummingMergeTree表而不做任何处理可能会得到重复汇总的结果必须使用sum函数或FINAL修饰符。2.3 与普通视图和Projection的区别为了避免混淆这里快速澄清几个概念普通视图VIEW只是一个保存的查询语句不存储数据。每次查询时执行底层SQL无性能提升仅简化查询。物化视图Materialized View存储实际数据通过触发器在写入时预计算用空间换时间显著提升查询性能。Projection这是ClickHouse 21.6版本引入的更强悍的特性。它也可以预聚合数据但其数据以“部分”的形式与主表物理存储在一起共享相同的分区和排序键。查询优化器可以自动选择是否使用Projection无需改写SQL。Projection可以看作是物化视图的“升级版”在数据一致性、存储效率和查询优化上更有优势但物化视图在灵活性如写入不同表和更复杂的ETL流水线中仍有其价值。对于大多数21.6版本之前的用户或者需要将聚合结果输出到独立表进行后续处理的场景物化视图仍然是核心工具。3. 从零到一创建你的第一个物化视图理论讲得再多不如动手做一遍。我们假设一个经典的场景有一个实时写入的用户行为日志表user_events我们需要一个按天和用户ID统计事件次数和总耗时的实时看板。3.1 环境与源表准备首先确保你有一个可用的ClickHouse环境。你可以通过clickhouse-client连接。我们创建源表通常使用MergeTree引擎并按日期分区以方便管理。-- 创建源表存储用户行为明细 CREATE TABLE default.user_events ( event_time DateTime, user_id UInt32, event_type String, duration_ms UInt32, device String ) ENGINE MergeTree PARTITION BY toYYYYMMDD(event_time) ORDER BY (user_id, event_time) SETTINGS index_granularity 8192;这张表按event_time的日期分区并按(user_id, event_time)排序适合按用户和时间范围的查询。3.2 创建目标表聚合表接下来创建用于存储聚合结果的目标表。我们将按event_date日期和user_id聚合因此使用SummingMergeTree引擎并指定(event_date, user_id)为排序键。SummingMergeTree会自动对非排序键的数值列event_count,total_duration进行求和。-- 创建目标表用于存储物化视图的聚合结果 CREATE TABLE default.user_events_daily ( event_date Date, user_id UInt32, event_count UInt64, total_duration UInt64 ) ENGINE SummingMergeTree PARTITION BY toYYYYMM(event_date) ORDER BY (event_date, user_id) SETTINGS index_granularity 8192;3.3 创建物化视图现在创建连接源表和目标表的物化视图。关键点是TO子句指定目标表以及AS SELECT定义了聚合逻辑。-- 创建物化视图 CREATE MATERIALIZED VIEW default.mv_user_events_daily TO default.user_events_daily AS SELECT toDate(event_time) AS event_date, user_id, count() AS event_count, sum(duration_ms) AS total_duration FROM default.user_events GROUP BY event_date, user_id;执行完这条语句后物化视图就进入了工作状态。它像一个挂在user_events表上的监听器开始等待新数据的到来。3.4 验证与测试让我们写入一些测试数据看看效果。-- 向源表插入测试数据 INSERT INTO default.user_events VALUES (2023-10-27 10:00:00, 1001, click, 120, iOS), (2023-10-27 10:01:00, 1001, view, 500, iOS), (2023-10-27 11:00:00, 1002, click, 80, Android), (2023-10-28 09:00:00, 1001, purchase, 2000, iOS);插入完成后不要直接查询物化视图mv_user_events_daily因为它本身不存储数据。我们应该查询目标表user_events_daily。-- 查询目标表查看聚合结果 SELECT * FROM default.user_events_daily ORDER BY event_date, user_id;你会看到类似这样的结果event_date | user_id | event_count | total_duration ------------|---------|-------------|--------------- 2023-10-27 | 1001 | 2 | 620 2023-10-27 | 1002 | 1 | 80 2023-10-28 | 1001 | 1 | 2000完美数据已经自动聚合好了。现在当你的应用需要查询每日用户行为统计时直接查这张小小的user_events_daily表速度会比扫描全量的user_events表快上百倍。实操心得在正式使用前务必用一个小批量数据测试整个链路插入源表 - 检查目标表。这能帮你提前发现表结构不匹配、聚合逻辑错误等问题。我曾经因为目标表字段顺序和SELECT输出不一致导致物化视图写入失败但错误日志并不总是那么直观。4. 高级用法与性能优化实战掌握了基础创建我们来看看如何在生产环境中用得更好、更稳。物化视图用不好反而会成为系统的负担。4.1 处理历史数据初始化如前所述物化视图只处理创建后的新数据。对于已有的海量历史数据我们需要手动“回填”。方法就是直接向目标表插入一个聚合查询的结果。-- 手动初始化历史数据到目标表 INSERT INTO default.user_events_daily SELECT toDate(event_time) AS event_date, user_id, count() AS event_count, sum(duration_ms) AS total_duration FROM default.user_events -- 假设物化视图是今天创建的我们初始化今天之前的所有数据 WHERE event_time 2023-10-27 00:00:00 GROUP BY event_date, user_id;重要警告如果源表数据量非常大比如上亿行直接运行上面的语句可能会把ClickHouse服务器内存打爆。务必分批进行-- 安全的方式按分区分批初始化 -- 首先找出所有需要处理的分区 SELECT DISTINCT partition FROM system.parts WHERE table user_events; -- 然后逐个分区执行INSERT...SELECT INSERT INTO default.user_events_daily SELECT ... FROM default.user_events WHERE partition_id 20231026 -- 替换为具体分区 GROUP BY ...;4.2 选择最优的聚合引擎与查询方式SummingMergeTree并非万能。根据聚合需求正确选择引擎和查询写法至关重要。场景一精确去重计数UV如果你需要统计每日活跃用户数UVSummingMergeTree无法直接做到因为count(distinct user_id)的结果不能简单相加。这时就需要AggregatingMergeTree和uniqState函数。-- 1. 创建存储聚合状态的目标表 CREATE TABLE default.user_daily_uv ( event_date Date, user_count_state AggregateFunction(uniq, UInt32) ) ENGINE AggregatingMergeTree PARTITION BY toYYYYMM(event_date) ORDER BY event_date; -- 2. 创建物化视图 CREATE MATERIALIZED VIEW default.mv_user_daily_uv TO default.user_daily_uv AS SELECT toDate(event_time) AS event_date, uniqState(user_id) AS user_count_state FROM default.user_events GROUP BY event_date; -- 3. 查询时使用uniqMerge函数解出最终结果 SELECT event_date, uniqMerge(user_count_state) AS daily_uv FROM default.user_daily_uv GROUP BY event_date ORDER BY event_date;场景二查询SummingMergeTree表的最佳实践直接SELECT * FROM summing_table可能会看到由于数据块未合并而导致的重复维度行。为了获得准确结果你应该-- 方法1使用sum函数对可能重复的维度进行再次聚合推荐可利用索引 SELECT event_date, user_id, sum(event_count) as final_event_count, sum(total_duration) as final_total_duration FROM default.user_events_daily GROUP BY event_date, user_id; -- 方法2使用FINAL修饰符强制在查询时合并数据 SELECT * FROM default.user_events_daily FINAL;方法1在大多数情况下更高效尤其是当你的查询条件能利用到ORDER BY键时。方法2FINAL会导致查询变慢因为它需要执行一次合并操作仅在数据量很小或调试时使用。4.3 监控与运维关键点物化视图运行在后台你需要知道它是否健康。检查物化视图是否挂起物化视图可能因为目标表写入失败如磁盘满、结构不兼容而自动禁用。SELECT name, is_dropped FROM system.tables WHERE engine MaterializedView;如果is_dropped为1就需要检查system.metric_log或clickhouse-server.err.log中的错误信息解决问题后使用DETACH和ATTACH语句重新挂载。查看数据同步延迟通过对比源表和目标表的数据行数或最新时间戳判断物化视图处理是否跟得上写入速度。-- 查看源表总行数 SELECT count() FROM user_events; -- 查看目标表总行数注意由于聚合行数没有直接可比性可对比最新分区时间 SELECT max(event_date) FROM user_events_daily;管理物化视图的生命周期删除DROP VIEW mv_name;注意这不会删除目标表及其数据。临时禁用DETACH VIEW mv_name;视图停止工作但元数据保留。重新启用ATTACH VIEW mv_name;修改ClickHouse的物化视图不支持ALTER修改其SELECT查询。必须DROP后重新CREATE。这是一个重大限制操作前一定要评估对业务的影响最好在低峰期进行。5. 常见“坑点”与排查技巧实录即使理解了原理在生产环境使用物化视图时依然会遇到各种意想不到的问题。下面是我和同事们用“血泪”换来的经验。5.1 数据不一致问题这是最令人头疼的问题。现象是源表有数据但目标表查不到或数据不对。排查步骤1确认物化视图是否生效。-- 查看物化视图的依赖关系和处理状态 SELECT * FROM system.tables WHERE name mv_user_events_daily; -- 查看最近是否有错误日志 SELECT * FROM system.part_log WHERE table user_events_daily AND event_type NewPart AND not empty(exception) ORDER BY event_time DESC LIMIT 5;排查步骤2检查写入是否触发了物化视图。物化视图只对INSERT有效。如果你是通过ALTER TABLE ... UPDATE/DELETE操作源表这些变更不会触发物化视图更新这是一个巨大的陷阱。对于需要更新删除的场景考虑使用CollapsingMergeTree或VersionedCollapsingMergeTree作为源表引擎并在物化视图的SELECT逻辑中处理“符号”sign列。排查步骤3检查SELECT逻辑中的函数和类型。例如在物化视图定义中使用了now()这样的非确定性函数会导致每次计算的结果都不同。确保SELECT语句是确定性的。5.2 写入性能下降问题为一张高频写入的大表创建多个复杂的物化视图可能会导致源表写入速度明显变慢。根因分析每个物化视图都是一个独立的触发器串行执行。如果物化视图的聚合逻辑复杂如多表JOIN、窗口函数计算耗时就会叠加到写入延迟上。解决方案合并物化视图如果多个物化视图从同一张源表聚合只是维度不同可以考虑创建一个更宽泛的物化视图存储更细粒度的数据然后通过查询时聚合来满足不同需求。但这会增加存储成本。使用Projection21.6版本如前所述Projection与主表数据存储在一起其计算和合并过程可能更高效。异步化处理对于延迟要求不高的场景可以不用物化视图而是使用INSERT INTO target_table SELECT ...语句通过定时任务如crontab或消息队列来异步更新聚合表。5.3 存储空间膨胀问题物化视图的目标表如果使用不当可能会快速膨胀。案例目标表使用了MergeTree而不是SummingMergeTree且物化视图的聚合粒度很细比如按秒导致产生大量小数据块合并速度跟不上写入速度。排查检查目标表的system.parts看是否有大量小的、未合并的数据块。SELECT table, partition, count() as part_count, sum(rows) as total_rows, sum(bytes_on_disk) as total_size FROM system.parts WHERE active AND table user_events_daily GROUP BY table, partition ORDER BY part_count DESC;优化确保使用正确的聚合引擎SummingMergeTree/AggregatingMergeTree。适当调整目标表的partition by键避免分区过多过细。调整合并策略的参数如merge_with_ttl_timeout但需谨慎。5.4 物化视图链与循环依赖你可以创建一个物化视图的目标表是另一张表而这张表又是另一个物化视图的源表形成一条链。这非常危险很容易创建出循环依赖A物化视图依赖B表B表的数据又来自A物化视图导致数据无限循环复制瞬间压垮集群。重要守则在设计物化视图链路时务必画出一个清晰的有向无环图DAG并严格审查。在测试环境充分验证数据流向。6. 与新一代特性Projection的对比与选型建议自从ClickHouse 21.6版本引入Projection后很多原本物化视图的用例有了更好的选择。了解它们的区别有助于你做技术选型。特性物化视图 (Materialized View)投影 (Projection)存储方式数据存储在独立的表中数据作为源表的一部分存储与主表数据共享分区和排序数据一致性最终一致依赖独立的合并过程强一致与主表数据原子性更新查询优化需要应用层改写查询或使用单独的查询语句优化器自动选择对查询透明无需改写SQL维护需要单独管理表删除、修改结构等作为表定义的一部分管理更方便灵活性可以将数据写入任何表甚至不同集群的表灵活性高紧密绑定源表灵活性较低适用场景1. 跨集群数据同步聚合2. 需要将聚合结果输出到不同引擎的表进行后续处理3. CH 21.6之前的版本1. 透明加速查询尤其是聚合和预聚合场景2. 希望简化架构减少需要维护的对象3. CH 21.6版本个人建议如果你的集群版本是21.6以上并且需求是透明地加速某些固定模式的聚合查询优先考虑使用Projection。它更简单、更安全、性能也往往更好。如果你需要将预处理后的数据输出到另一个系统或者进行更复杂的、多步骤的ETL管道那么物化视图的灵活性仍然是不可替代的。例如你可以用一个物化视图将数据聚合后再写入一张Kafka引擎的表流向其他数据流处理系统。物化视图是ClickHouse生态中一个经典且强大的功能理解其“触发器”本质和与存储引擎的配合是高效使用它的关键。随着Projection的成熟部分场景可以被替代但在许多复杂的数据流水线中物化视图依然扮演着核心角色。在实际应用中多监控、多测试从小处着手逐步构建你的预计算体系才能让这个“神器”真正为你的数据分析提速而不是添乱。

相关新闻

长沙高薪企业行业分布与求职策略解析

长沙高薪企业行业分布与求职策略解析

1. 长沙高薪企业榜单解析:行业分布与薪资水平长沙作为湖南省会城市,近年来经济发展迅速,形成了以工程机械、电子信息、文化创意等为主的产业集群。这份高薪企业榜单反映了长沙当前就业市场的高价值岗位分布情况。从行业分布来看,榜…

2026/8/23 21:54:42 阅读更多 →
Java大厂面试深度解析:核心技术、框架与分布式系统

Java大厂面试深度解析:核心技术、框架与分布式系统

1. 互联网大厂Java面试全景解析刚结束字节跳动三面技术考核的候选人张明(化名)在茶水间整理笔记时,突然被面试官叫住:"你刚才提到ConcurrentHashMap的扩容机制,能具体说说触发扩容的阈值计算方式吗?&q…

2026/8/23 21:53:42 阅读更多 →
制造业来料管理实战指南:从检验到协同的质量控制体系

制造业来料管理实战指南:从检验到协同的质量控制体系

1. 项目概述:为什么“来料管理”是生产质量的命门干了十几年制造业,从一线质检员做到质量总监,我最大的体会就是:质量是生产出来的,但源头是管出来的。这个“源头”,十有八九指的就是“来料管理”。很多工厂…

2026/8/23 21:53:42 阅读更多 →

最新新闻

DeepSeek开源一周,Agent第一次有了“组织“

DeepSeek开源一周,Agent第一次有了“组织“

上周我们聊了 DeepSeek Harness(DSH)和它背后那篇 Cordis 论文。论文的结尾有一句话,说未来要让 AI"持续生成并替换自己的组件"——也就是 Agent 自己给自己升级。 当时觉得那是个很远的愿景。 结果一周过去,"自进…

2026/8/23 22:37:10 阅读更多 →
OpenKylin虚拟机安装全攻略:从零到精通的详细步骤与避坑指南

OpenKylin虚拟机安装全攻略:从零到精通的详细步骤与避坑指南

1. 项目概述:为什么选择OpenKylin?最近在折腾国产操作系统,OpenKylin(开放麒麟)这个名字出现的频率越来越高。它作为一款基于Linux内核、由国内社区主导开发的开源桌面操作系统,主打安全、易用和良好的中文…

2026/8/23 22:37:10 阅读更多 →
0xc000012f 错误怎么修复?先修运行库和系统组件,再决定是否重装软件

0xc000012f 错误怎么修复?先修运行库和系统组件,再决定是否重装软件

运行 Windows 软件时弹出 0xc000012f,通常意味着某个程序或它依赖的组件没有通过系统加载校验。遇到这种提示,优先检查系统 DLL、运行库和启动环境是否完整,再根据报错范围判断要不要重装出错应用。单独从网上下载 DLL 来替换,往往…

2026/8/23 22:36:09 阅读更多 →
在Typora中用HTML实现复杂表格:突破Markdown表格限制

在Typora中用HTML实现复杂表格:突破Markdown表格限制

1. 从Markdown的局限到HTML的灵活:为什么我们需要在Typora里写表格代码如果你和我一样,长期使用Typora作为主力Markdown编辑器,那你一定对它的简洁优雅和即时渲染爱不释手。写个简单的表格,用几个竖线和短横线就能搞定&#xff0c…

2026/8/23 22:36:09 阅读更多 →
Windows Installer 服务无法访问怎么办?MSI 安装链路修复与排查要点

Windows Installer 服务无法访问怎么办?MSI 安装链路修复与排查要点

安装 .msi 程序时出现“Windows Installer 服务无法访问”,通常意味着 MSI 安装链路中某个环节没有就绪。报错可能来自服务状态、组件注册、系统目录或权限策略中的任意一环,单靠更换安装包不一定能解决。处理顺序建议先从系统软件组件入手,再…

2026/8/23 22:36:09 阅读更多 →
Windows API 实战指南:从原理到自动化与系统管理

Windows API 实战指南:从原理到自动化与系统管理

1. 从“黑盒”到“工具箱”:理解Windows API的本质如果你在Windows上写过代码,或者尝试过一些自动化脚本,那你一定或多或少接触过“Windows API”这个词。它听起来很高大上,像是系统深处某个神秘的黑盒。但今天,我想把…

2026/8/23 22:35:09 阅读更多 →

日新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →