<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>性能优化 on 老张开工了</title>
    <link>/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/</link>
    <description>Recent content in 性能优化 on 老张开工了</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Fri, 17 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>ETL 性能优化技巧</title>
      <link>/posts/2026/04/etl-performance/</link>
      <pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate>
      <guid>/posts/2026/04/etl-performance/</guid>
      <description>瓶颈在哪里 ETL 性能优化最忌讳的事就是一上来到处调参数。没有找到真正的瓶颈之前，所有的优化都是瞎蒙。&#xA;先搞清楚一个基本事实：ETL 管道中最慢的环节决定了整体速度。这个瓶颈可能出现在抽取阶段（网络带宽限制）、转换阶段（CPU 算力不足）、或者加载阶段（数据库写入太慢）。&#xA;定位瓶颈的基本方法是用监控工具观察每个阶段的耗时和资源消耗。一个简单的做法是在管道中埋点记录时间：&#xA;import time from contextlib import contextmanager @contextmanager def measure_stage(stage_name, logger=None): &amp;#34;&amp;#34;&amp;#34;记录每个阶段的耗时&amp;#34;&amp;#34;&amp;#34; start = time.time() start_mem = get_memory_usage() try: yield finally: elapsed = time.time() - start end_mem = get_memory_usage() print(f&amp;#34;[{stage_name}] 耗时: {elapsed:.2f}s, &amp;#34; f&amp;#34;内存: {start_mem:.0f}MB → {end_mem:.0f}MB &amp;#34; f&amp;#34;(增量: {end_mem - start_mem:.0f}MB)&amp;#34;) 在实际案例中，我曾见过一个团队花了两周优化 SQL 查询，把转换阶段从 2 小时降到 20 分钟，但整体 ETL 仍然跑了 3 小时——因为他们没发现瓶颈其实在加载阶段，数据库写入速度跟不上。&#xA;并行处理 并行是加速 ETL 最直接的手段。可以把一个大任务拆分成多个小任务同时执行。&#xA;数据分区并行 把数据按某个维度分成多个分区，每个分区独立处理。分区方式包括：&#xA;按时间分区：每天的数据一个分区，多天的数据可以并行处理 按范围分区：按 ID 范围拆分，比如 1-100 万、100 万-200 万 按业务维度：按地区、产品类别等业务字段拆分 import concurrent.</description>
    </item>
    <item>
      <title>索引与性能优化</title>
      <link>/posts/2025/02/index-and-performance/</link>
      <pubDate>Thu, 13 Feb 2025 10:00:00 +0800</pubDate>
      <guid>/posts/2025/02/index-and-performance/</guid>
      <description>数据量达到百万级后，不合适的索引会让查询慢如蜗牛。本章将系统学习 PostgreSQL 的索引原理和性能优化方法。&#xA;为什么需要索引？ 没有索引的查询需要全表扫描——逐行检查数据。就像一本没有目录的书，要找一句话就得从头翻到尾。&#xA;索引的本质是一个排序过的数据结构（B-Tree），让数据库能在 O(log n) 时间内找到数据，而不是 O(n)。&#xA;创建练习数据 -- 创建一张大表来演示索引效果 CREATE TABLE big_orders ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL, product_name VARCHAR(100), amount NUMERIC(10,2), status VARCHAR(10), order_date DATE, created_at TIMESTAMP DEFAULT NOW() ); -- 插入 100 万条数据 INSERT INTO big_orders (user_id, product_name, amount, status, order_date) SELECT (random() * 100000)::INT + 1, CASE (random() * 5)::INT WHEN 0 THEN &amp;#39;笔记本电脑&amp;#39; WHEN 1 THEN &amp;#39;手机&amp;#39; WHEN 2 THEN &amp;#39;耳机&amp;#39; WHEN 3 THEN &amp;#39;运动鞋&amp;#39; ELSE &amp;#39;T恤&amp;#39; END, (random() * 5000 + 100)::NUMERIC(10,2), CASE (random() * 4)::INT WHEN 0 THEN &amp;#39;已完成&amp;#39; WHEN 1 THEN &amp;#39;已取消&amp;#39; WHEN 2 THEN &amp;#39;退款中&amp;#39; ELSE &amp;#39;已完成&amp;#39; END, DATE &amp;#39;2024-01-01&amp;#39; + (random() * 730)::INT FROM generate_series(1, 1000000); -- 确认数据已插入 SELECT count(*) FROM big_orders; EXPLAIN 读懂查询计划 -- 查看查询计划 EXPLAIN SELECT * FROM big_orders WHERE user_id = 42; EXPLAIN ANALYZE SELECT * FROM big_orders WHERE user_id = 42; EXPLAIN 输出解读：</description>
    </item>
  </channel>
</rss>
