尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
SQL Server性能分析:Profiler与Read80Trace实战
简介SQL Server 2000性能工具Profiler是一份面向数据库管理员与开发人员的文档资料围绕SQL Server Profiler这款图形化实时监视工具展开系统讲解其在数据库行为监视、慢SQL定位、死锁与错误跟踪中的实际应用。资源仅包含1个doc文档压缩包大小308KB内容精炼便于离线查阅。目前已有597人学习下载。文档内容从打开Profiler、新建跟踪、配置事件与数据列到分析跟踪结果逐步演示T-SQL语句与存储过程执行情况的捕获进一步深入跟踪模板、Read80trace工具的Normalization功能、usp_GetAccessPattern存储过程分析技巧并讨论如何识别“HOT数据库”与常见性能瓶颈。通过完整阅读并动手实践读者能掌握Profiler的使用要领学会将跟踪数据存储到文件或表中进行回放分析有针对性地优化SQL语句、索引及锁策略提升SQL Server 2000环境下的运维与调优能力。1. SqlServer2000 性能工具 Profiler从一条慢 SQL 到全局访问模式十年前没有那么多云监控和智能诊断SQL Server 2000 时代排查数据库性能问题DBA 手里最顺手的工具就是 Profiler——SQL 事件探查器。它是图形化实时监视工具能看到每一个连接到服务器上执行的 T-SQL 语句、存储过程调用、死锁、错误日志也能把这一切存成 .trc 文件事后回放。这篇文章要拆的这份《SqlServer2000性能工具Profiler.doc》前半部分讲 Profiler 的打开方式和跟踪创建后半部分讲用 Read80Trace 工具和自定义存储过程分析超大 Trace 文件最终输出数据库的访问模式报表。对还在维护老系统的 DBA、需要从历史 Trace 里挖性能瓶颈的工程师来说这份文档能直接拿来当操作手册用。它的核心价值不在 Profiler 基础操作而在后半部分当 Trace 文件大到 GB 级传统方法全部失效时怎么用 Normalization 思维把几十万条 SQL 归并成几十类再定位真正吃掉 CPU 和磁盘的那几条。2. 第一次跟踪就这么配事件选择、数据列和过滤条件的门道2.1 打开 Profiler 的路径和连接前的两个选择在 SQL Server 2000 的企业管理器里工具菜单下直接能找到 SQL Profiler新建跟踪后第一步是连接到目标服务器。这里有两个选择要注意跟踪类型选 Shared 还是 Private。Shared 类型下所有能登录到 Profiler 所在服务器的用户都能看到这个跟踪多人协作排查问题时方便Private 只有创建者能用。我一般自己排查服务器问题时选 Private避免别人误操作改动跟踪配置。连接上服务器后会弹出跟踪属性对话框这里定义跟踪名称、输出方式。输出方式有 Capture to file 和 Capture to table 两个选项。存文件会减少内存开销因为 Profiler 可以直接把事件流写入文件存表则容易引起较大的额外系统开销因为每条事件都要执行一次 INSERT。分析用的话建议存文件扩展名 .trc后续 Read80Trace 也认这个格式。2.2 只选必要事件监视太多反而毁了跟踪本身事件标签页是跟踪配置的核心。可用事件列表里能看到 SQL Server 2000 支持的全部事件类别添加事件时底部会显示该事件的说明文字。实际生产环境跟踪我建议只选这几类登录连接的失败、成功或断开连接DELETE、INSERT、UPDATE 命令远程存储过程调用 RPC 的状态存储过程的开始或结束以及存储过程中的每一条语句写入 SQL Server 错误日志的错误打开的游标向数据库对象添加锁或释放锁。提示不要为了「全面」把所有事件都勾上。对事件进行监视本身会增加系统负担而且跟踪文件会以极快速度膨胀成 GB 级。你只是想看慢语句结果把锁等待、游标操作、连接断开全录进来了后面分析时噪音比信号还多。2.3 数据列和过滤条件的组合思路数据列标签页选择每个事件要记录哪些字段。排查性能问题时TextData语句文本、CPU、Reads、Writes、Duration、StartTime、LoginName 这些列必须选上。Reads 列表示语句执行的逻辑读页面数以 8K 为单位这是衡量语句对磁盘和内存压力的关键指标Duration 是语句执行耗时毫秒单位。过滤条件是最容易被忽视但最实用的一步。在 Filters 标签页可以设置只捕获满足条件的事件比如只捕获 CPU 大于 100 毫秒的语句或者只捕获某个特定数据库的语句。我的习惯是先在不过滤的情况下跑 10 分钟看清这个系统大概有哪些语句类型再决定过滤条件。一上来就过滤容易漏掉那些单次执行很快但调用量巨大的小语句。2.4 跟踪的启停和事后打开方式跟踪创建完成并运行后跟踪窗口会实时显示每条达到过滤条件的 T-SQL 语句。网页应用做操作时窗口里依次滚动出对应语句点暂停可以冻结画面逐条检查。排查完可以选中可疑语句右键直接复制到查询分析器里单步执行验证。打开已有跟踪文件的方法是文件菜单 → 打开 → 跟踪文件选择 .trc 文件。除了 .trcProfiler 也能打开 .log 日志文件和普通 SQL 脚本文件。要注意的是Profiler 直接打开几 GB 的大文件会非常卡加载就要好几分钟鼠标拖动都费劲这时候就该用 Read80Trace 这种命令行工具了。3. 把模板选对五种预定义模板的适用边界和配置思路3.1 模板是什么以及为什么不用从零配模板是预定义好的事件类和数据列组合定义保存后可以反复用于多个跟踪模板本身不会执行。SQL Server Profiler 提供了几个预定义模板分别对应不同的排查场景。新手最常犯的错是无论什么场景都用 Standard 模板抓回来的数据要么太杂要么缺关键列二次分析成本很高。创建自定义模板的位置在文件菜单 → 模板 → 新建模板。新建时可以选择基于某个现有模板修改也可以从空模板开始——空模板不包含任何事件类适合完全按自己的思路配置的场景。比如我只想抓特定存储过程的执行情况空模板加上 RPC:Starting、SP:Completed、SP:StmtStarting 这几个事件就够了。3.2 预定义模板的功能定位和事件组成对比文档里列了一张预定义模板表对照实际使用场景看会更清楚模板名称主要用途关键事件类Standard通用跟踪起点记录常规数据库活动Audit Login、Audit Logout、ExistingConnection、RPC:Completed、SQL:BatchCompleted、SQL:BatchStartingTSQL调试客户端应用程序捕获所有提交的 T-SQL 语句RPC:Starting、SQL:BatchStartingTSQL_Duration识别慢查询按持续时间分组RPC:Completed、SQL:BatchCompletedTSQL_Grouped调查某客户端或用户发出的查询按 LoginName 分组的 TSQL 事件TSQL_Replay重播跟踪用于迭代优化和基准测试包含游标系列、RPC 系列、SQL:Batch 系列TSQL_SPs分析存储过程组成步骤和重编译问题RPC:Starting、SP:Starting、SP:Completed、SP:StmtStartingTuning供数据库引擎优化顾问用作工作负荷RPC:Completed、SP:StmtCompleted、SQL:BatchCompleted调试客户端应用时应该选 TSQL它能捕获客户端提交的所有语句和发出时间方便定位应用到底发了什么 SQL。识别慢查询用 TSQL_Duration它按执行时间分组很快能看出哪些语句耗时最长。TSQL_SPs 适合怀疑存储过程被反复重编译的场景——文档里特别提醒如果怀疑过程正在重新编译要添加 SP:Recompile 事件这在默认模板里是没有的。3.3 默认模板的坑旧模板改配置后新跟踪不生效SQL Server Profiler 自动指定 Standard 作为所有新跟踪的默认模板。如果你改了 Standard 模板比如新增了一个事件列但新创建的跟踪还是按旧配置跑那是因为「用作所选服务器类型的默认模板」复选框没勾上。修改模板时必须在跟踪模板属性的常规选项卡里选中这个复选框改动才会对所有后续新跟踪生效。这个坑我踩过好几次排查半天发现是新跟踪用的还是老配置。4. 拆掉大 Trace 文件的黑匣子Read80Trace 的 Normalize 逻辑和分析链路4.1 传统分析方法的两个硬伤跟踪文件小的时候直接在 Profiler 里用过滤功能或者把 trace 导入数据库再用 T-SQL 统计都能出结果。但文件一旦到了 GB 级这两个方法就失灵了。第一个硬伤是分析极难文件巨大导致加载慢、查询慢你很难从全局看出哪类语句占比高容易被个别执行时间长的语句吸引注意力把精力耗费在其实并不关键的问题上。第二个硬伤更隐蔽——大量语句模式类似但参数不同比如 WHERE au_lname white 和 WHERE au_lname green在 trace 文件里是两条完全不同的记录你没有一个简单办法把它们归类到一起统计导致无法形成访问模式。4.2 Read80Trace 的原理和核心价值Read80Trace 是微软官方提供的一个命令行工具RML 工具包的一部分它的核心功能有三个读取 trace 文件、对语句做 Normalize标准化、把结果导入数据库并生成 HTML 分析页面。Normalization 是这个工具的灵魂——它把模式相同但参数不同的语句全部归类到一起。原始语句select * from authors where au_lname white select * from authors where au_lname green select * from authors where au_lname carson标准化之后变成同一条select * from authors where au_lname {str}参数值被替换成了类型占位符语句模式保留。有了标准化后的语句就能对几十万条 trace 记录做 group by 统计得到「运行最频繁的语句」「最影响系统性能的关键语句」「各类语句群占用的比例」这三个信息合起来就是数据库系统的访问模式。访问模式之所以可靠是因为一个系统的业务模块基本固定每个模块访问数据库的方式基本不变只要采样时间足够长语句构成和占比就趋于稳定。文档建议至少跑 2 小时以上。4.3 命令行参数怎么用Read80Trace 的常用命令格式Read80trace -f -dmydb -Imytrace.trc参数含义-f不生成 RML 文件。RML 文件用于 OStress 工具多线程重放 trace 事件不需要重放功能时一定要加这个参数RML 文件非常大生成它纯属浪费磁盘空间-d指定结果输出到哪个数据库后面跟数据库名这里是 mydb。Read80Trace 会在该数据库中建表存放处理结果-I指定要分析的 trace 文件名注意是大写 IRead80Trace 有个很聪明的行为如果目录下存在一系列连续命名的 trace 文件比如 mytrace.trc、mytrace1.trc、mytrace2.trc它不会只处理指定的第一个而是会挨个顺序读取全部处理完。这个特性对长时间采样生成的多段文件特别有用不用手动合并。另外还有个小写-i参数支持直接从 zip 或 CAB 压缩包中读取 trace 文件不用自己解压能省不少临时磁盘空间。处理完的产物有三个标准化后的语句存入 tblBatches 表和 tblUniqueBatches 表统计报表以 HTML 页面形式输出还有供 OStress 使用的 RML 文件如果没加 -f。文档里提到在内存仅 512MB 的老机器上分析几个 GB 的 trace 文件不到一小时就能跑完这个性能在当时已经相当能打。4.4 分析生产 trace 还是压力测试 trace这里有个选型建议值得单独说Read80Trace 虽然也能处理压力测试产生的 trace 文件但文档明确建议优先分析生产环境的 trace。原因是很多压力测试工具并不能真正模拟现实环境或者干脆循环执行自己写死的语句得到的 trace 文件不能真实反映实际访问模式。压力测试 trace 只能作为参考不能作为优化依据。判断一个系统的访问模式需要的是真实业务下足够长的采样窗口而不是人为构造的负载。5. 避坑与排查Read80Trace 和存储过程的五个高频翻车现场5.1 int 溢出导致存储过程报错现象运行 usp_GetAccessPattern 时抛出 int 整数溢出错误尤其在数据量大或者采样时间长的时候。原因Read80Trace 生成的 tblBatches 表中 reads、cpu、writes 这三个字段类型是 int取值范围约 ±21 亿。当 trace 里语句数量大、累计的 reads 总量超过这个上限时SUM() 聚合就会溢出。解决先把字段类型改成 bigint 再跑统计。执行alter table tblBatches alter column reads bigint alter table tblBatches alter column cpu bigint alter table tblBatches alter column writes bigint注意三条必须都执行只改 reads 的话cpu 或 writes 累加量大的时候还会再次翻车。5.2 duration 过滤参数设得太小导致结果失真现象用 usp_GetAccessPattern 加参数过滤时比如传入 100、200 这种小值输出结果和不带参数的结果几乎一样看不出过滤效果。原因duration_filter 以毫秒为单位如果系统整体响应很快大部分语句执行时间都在几百毫秒以内低于阈值过滤条件形同虚设。解决参数不要小于 1000建议用 1000 的倍数3000 或 5000。这个参数的意义是筛出真正耗时的语句单独分析。我习惯同时跑四组不带参数、1000、3000、5000交叉比对结果。5.3 跟踪文件大小失控撑爆磁盘现象跟踪跑了半小时磁盘可用空间急剧下降.trc 文件以每分钟几十 MB 的速度增长。原因事件选得太多尤其是把 Lock:Acquired、Lock:Released、Cursor 系列事件全部勾上每条语句都可能触发几十条锁事件文件膨胀极快。解决只保留本次排查必需的事件。排查慢查询就选 RPC:Completed、SQL:BatchCompleted 加 SP:StmtCompleted锁相关的问题单独开一个只含锁事件的跟踪。另外一个习惯是给跟踪文件设置最大文件大小Profiler 的跟踪属性里有这个选项超过大小自动停止或滚动。5.4 Read80Trace 处理结果导入后生成的表结构不完整现象Read80Trace 跑完后目标数据库里没有 tblBatches 表或者表存在但没有 NormText 字段。原因最常见的是指定的数据库不对。-d参数指定的数据库必须是已存在的库Read80Trace 不会自动建库。另一个可能是 Read80Trace 版本太老不认识新版 Profiler 生成的文件格式。解决先手工建一个空数据库再跑 Read80Trace确保连接账号对该库有建表权限。格式不兼容的情况检查 trace 文件是不是 SQL Server 2005 或更高版本导出的——Read80Trace 对部分新版本文件的解析会有兼容性问题。5.5 用 Profiler 直接打开 GB 级 trace 文件导致界面卡死现象Profiler 加载大文件时进度条长时间不动鼠标操作无响应最后只能强制结束进程。原因Profiler 的图形界面是单线程加载几 GB 的文件要逐行解析并渲染列内存和 CPU 都不够用。解决这种场景直接用 Read80Trace 处理或者用 trace 导入功能把 .trc 文件导入到数据库表中再用 T-SQL 查询分析。小文件用 Profiler 打开没问题超过 200MB 就考虑换工具。6. 存储过程出报表usp_GetAccessPattern 实战与 HOT 数据库定位技巧6.1 存储过程逻辑拆解usp_GetAccessPattern 的核心思路可以拆成三步先算全体语句的性能总和作为分母再按标准化后的语句文本分组统计最后按不同指标排序输出 Top 10。完整定义如下Create procedure usp_GetAccessPattern duration_filter int -1 as begin declare sum_total float, sum_cpu float, sum_reads float, sum_duration float, sum_writes float -- 所有语句的汇总值乘以 0.01 是为了后续算比例时避免除零 select sum_total count(*) * 0.01, sum_cpu sum(cpu) * 0.01, sum_reads sum(reads) * 0.01, sum_writes sum(writes) * 0.01, sum_duration sum(duration) * 0.01 from tblBatches where duration duration_filter -- 按标准化语句分组输出执行次数、CPU、Reads、Duration 及各自占比 select ltrim(str(count(*))) exec_stats, str(count(*) / sum_total, 4, 1) % ExecRatio, ltrim(str(sum(cpu))) : ltrim(str(avg(cpu))) cpu_stats, str(sum(cpu) / sum_cpu, 4, 1) % CpuRatio, ltrim(str(sum(reads))) : ltrim(str(avg(reads))) reads_stats, str(sum(reads) / sum_reads, 4, 1) % ReadsRatio, ltrim(str(sum(duration))) : ltrim(str(avg(duration))) duration_stats, str(sum(duration) / sum_duration, 4, 1) % DurRatio, textdata, count(*) / sum_total tp, sum(cpu) / sum_cpu cp, sum(reads) / sum_reads rp, sum(duration) / sum_duration dp into #queries_staticstics from ( select reads, cpu, duration, writes, convert(varchar(2000), NormText) textdata from tblBatches inner join tblUniqueBatches on tblBatches.HashId tblUniqueBatches.hashid where duration duration_filter ) B group by textdata print Top 10 order by cpureadsduration select top 10 * from #queries_staticstics order by cp rp dp desc print Top 10 order by cpu select top 10 * from #queries_staticstics order by cp desc print Top 10 order by reads select top 10 * from #queries_staticstics order by rp desc print Top 10 order by duration select top 10 * from #queries_staticstics order by dp desc print Top 10 order by batches select top 10 * from #queries_staticstics order by tp desc end关键点说明tblBatches 是 Read80Trace 生成的明细表每条记录对应 trace 中一条语句tblUniqueBatches 存放所有标准化后的唯一语句文本。两个表通过 HashId 关联HashId 就是标准化的标识同一模式不同参数的语句共享同一个 HashId。分组依据是 textdata也就是标准化后的语句文本这就是 Normalization 能归并同类语句的底层逻辑。输出中的 cp、rp、dp 分别代表该类语句 CPU、Reads、Duration 占总量的比例三项和排序能快速找出综合影响最大的语句。6.2 从报表到结论的实战解读文档里那个 8 个 CPU 全部 90%100% 波动的案例很有参考价值。系统运行缓慢用 PSSDIAG 采样 2 小时分析后报表显示存储过程 DBO.x_DEDUP_PROC 两小时内执行了 75 次平均 CPU 时间 681961 毫秒约 11 分钟占全部 CPU 资源的 90.8%Reads 占 94.6%。这个结果说明该存储过程几乎在连续不断地运行——单 CPU 两小时最多执行约 10 次60×2 ÷ 118 个 CPU 总共最多 80 次实际跑了 75 次意味着它把系统资源基本吃满了。这类语句就是真正的关键瓶颈优化它等于解决系统的主要问题。另一个容易犯的误判是盯着执行次数最多的语句。报表里最频繁的语句往往是SET QUOTED_IDENTIFIER这类环境配置语句对性能没有参考价值。真正该关注的是那些执行次数占比高且资源占比也可观的语句。比如某个案例里SELECT COUNT(*) FROM x_PROCESS_STATS这类语句占 8.2% 的执行比例这种高频小查询如果每次都要全表扫微小的优化也会因为放大效应给系统带来可观收益——这是文档里特别强调的一个思路。6.3 找出哪个库是 HOT 库当一台 SQL Server 实例上挂着多个数据库时需要先判断哪个库消耗资源最多这决定了优化方向从哪下手。思路和按语句分组一样只是把分组键换成 dbiddeclare sum_total float, sum_cpu float, sum_reads float, sum_duration float, sum_writes float select sum_total count(*) * 0.01, sum_cpu sum(cpu) * 0.01, sum_reads sum(reads) * 0.01, sum_writes sum(writes) * 0.01, sum_duration sum(duration) * 0.01 from tblBatches select dbid, ltrim(str(count(*))) exec_stats, str(count(*) / sum_total, 4, 1) % ExecRatio, ltrim(str(sum(cpu))) : ltrim(str(avg(cpu))) cpu_stats, str(sum(cpu) / sum_cpu, 4, 1) % CpuRatio, ltrim(str(sum(reads))) : ltrim(str(avg(reads))) reads_stats, str(sum(reads) / sum_reads, 4, 1) % ReadsRatio, ltrim(str(sum(duration))) : ltrim(str(avg(duration))) duration_stats, str(sum(duration) / sum_duration, 4, 1) % DurRatio, count(*) / sum_total tp, sum(cpu) / sum_cpu cp, sum(reads) / sum_reads rp, sum(duration) / sum_duration dp into #queries_staticstics_groupbydb from ( select reads, cpu, duration, writes, convert(varchar(2000), NormText) textdata, dbid from tblBatches inner join tblUniqueBatches on tblBatches.HashId tblUniqueBatches.hashid ) b group by dbid order by sum(reads) desc select dbid, ExecRatio batches, CPURatio CPU, ReadsRatio Reads, DurRatio Duration from #queries_staticstics_groupbydb报表里 dbid 对应的库名可以通过select name, dbid from master..sysdatabases查出来。拿到按库分组的资源占比后HOT 库一目了然——那个 CPU 或 Reads 占比远高于其他库的 dbid 就是重点优化对象。如果 HOT 库的占比超过 70%优化的重心就不用犹豫集中火力处理这个库里的关键语句即可。6.4 多参数交叉分析的习惯运行存储过程时我每次都会同时跑四组参数不带参数看全局访问模式再分别带 1000、3000、5000 毫秒过滤看慢语句集合。四组结果交叉比对重点看不同过滤条件下反复出现的语句——这些语句同时出现在高频列表和慢语句列表中说明它们既被频繁调用又单次耗时大是最值得优先优化的目标。从那以后我每次做 SQL Server 性能排查都强制走一遍这个流程Profiler 采集两小时以上Read80Trace 做 Normalizeusp_GetAccessPattern 出四组报表最后按 dbid 分组确认 HOT 库。这套流程帮我避开了无数「凭感觉定位慢 SQL」的弯路希望也能帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

游戏引擎架构深度解析:游戏对象与资源管理的核心实践

游戏引擎架构深度解析:游戏对象与资源管理的核心实践

1. 先从游戏对象说起:引擎里"万物皆对象"到底是怎么落地的做引擎开发这么多年,我一直觉得"游戏对象"(Game Object)和"资源管理"这两个词,是最容易被新手高估、也最容易被老手低估的东西…

📅 2026/10/12 2:37:34
Muse Gadgets:AI硬件开发的最小可行接口层

Muse Gadgets:AI硬件开发的最小可行接口层

/* 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 2:37:34
工控机死机与通讯掉线?变频器电磁干扰的接地与屏蔽实战方案

工控机死机与通讯掉线?变频器电磁干扰的接地与屏蔽实战方案

/* 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 2:32:33
MORE NEWS

更多资讯

📰

4G-5G互操作参数核查实战指南:定位SIB24异常与Fast Return失效

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

📰

STM32寄存器级编程实战:从GPIO到NVIC的白话手册

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

📰

车载氛围灯从能亮到可验收:BLE、分区灯控与OTA全流程实践

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

📰

STM32寄存器白话手册:从点灯到硬件直觉的底层编程指南

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

📰

Spring Boot热部署实战:DevTools配置、原理与常见问题排查

1. 为什么花大力气搞热部署1.1 从一次加班说起最早接触热部署,是某次在本地联调一个订单回调接口。改一行日志级别,重启一次服务,启动耗时大约四十秒,再加上IDE编译和连接池初始化,一次改动能磨掉两三分钟。那天下午光…

📰

用Claude Code与Docker Compose快速部署Mattermost私有聊天平台

前一阵帮一个团队搭内部沟通平台,最后选了 Mattermost 社区版。它开源、可自托管,数据都在自己服务器上,对于不喜欢把内部聊天记录放到第三方平台的小团队来说,是那种一眼看到就会记下来的方案。真正让我改办事风格的,…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬