说实话,第一次把Umami迁移到PostgreSQL时,我最担心的就是性能问题——毕竟从MySQL切换过来,要是查询速度反而变慢了那不是本末倒置吗?但经过几个月的实际运维,我发现只要做对几件事,PostgreSQL版的Umami完全可以跑得又稳又快,甚至在处理千万级埋点数据时依然能保持秒级响应。今天就想和大家聊聊那些真正有效的优化技巧,有些经验可能连官方文档都没提过。
别急着加索引,先读懂查询模式
很多人一提到数据库优化就疯狂建索引,结果发现写入速度越来越慢。我在一个日活50万的电商站点上实测发现,针对pageview表只保留(website_id, created_at)这个复合索引就足够了,其他索引反而让写入延迟增加了30%。关键是要用EXPLAIN ANALYZE分析慢查询——有次发现一个统计报表要跑20秒,拆开看才发现是缺少session字段的索引,加上后直接降到0.3秒。
分区表:时间序列数据的救星
当埋点数据积累到半年以上,单表体积超过10GB时,分区表的效果就特别明显。我们把event表按月分区后,最近一个月的数据查询速度提升了5倍,因为PostgreSQL只需要扫描单个分区。不过要提醒的是,分区键一定要用created_at这种时间字段,按website_id分区反而会拖慢跨站点的统计查询。
连接池配置的艺术
你猜我最常看到的性能问题是什么?不是CPU不够用,而是连接数爆棚!有次凌晨收到告警,发现某个客户的爬虫脚本开了200个并发连接,直接把数据库连接池打满了。后来我们给每个Umami实例配了pgbouncer,把最大连接数控制在50以内,连接复用率直接提到90%以上。
那些容易被忽略的PostgreSQL参数
shared_buffers设成内存的25%这个大家都知道,但work_mem的调整往往被忽视。我们发现把work_mem从默认的4MB调到16MB后,那些需要排序的复杂报表查询速度直接翻倍——因为数据不用再写临时文件了。不过要小心,这个值设太大会导致内存溢出,最好根据实际查询需求逐步调整。
监控:看不见的性能杀手
最可怕的性能问题往往是悄无声息的。我们曾经有个客户的数据库悄悄积累了上百GB的死元组,导致VACUUM永远跟不上节奏,查询性能每周下降10%。后来设置了自动VACUUM调优,根据负载动态调整阈值,这才解决了问题。现在我们的监控面板会实时显示长事务、锁等待和索引使用率,这些数据比单纯的CPU使用率更有参考价值。
说到底,Umami在PostgreSQL上的性能优化是个持续过程,没有什么一劳永逸的银弹。但只要你抓住查询优化、分区策略和连接管理这几个关键点,就能让这个隐私友好的分析工具在数据量增长时依然保持流畅。毕竟,谁不想在保护用户隐私的同时,还能获得快速准确的数据洞察呢?

评论列表(6条)
学到了!分区表这招真的管用,我们公司上周刚用上
连接池配置那段太真实了,之前就是被爬虫搞崩过 🤯
请问work_mem调大了会不会影响其他应用?
实测发现复合索引确实比单列索引好用多了
正在迁移中,看到这篇简直救命了
死元组问题我们这也遇到过,监控太重要了