




物化视图预计算高频聚合可提升性能10倍以上,需注意刷新策略与索引;避免SELECT *及大字段拖累I/O;近似算法可平衡精度与响应;务必验证分区裁剪是否生效。
当分析需要固定维度(如按天/按地区/按用户等级)反复统计时,实时 GROUP BY + SUM() 会持续拖慢查询。物化视图把结果存成物理表,查询直接走索引扫描,性能提升常达 10x 以上。
注意点:
CREATE MATERIALIZED VIEW + 定期 REFRESH MATERIALIZED VIEW;MySQL 不原生支持,得用普通表 + 应用层定时任务或触发器维护CREATE IN
DEX ON sales_by_day (date)
分析查询若包含 TEXT、JSONB 或 BLOB 字段,即使不参与计算,也会强制数据库读取、传输、序列化整块数据,显著放大 I/O 和网络开销。
实操建议:
SELECT 真正用于计算或展示的列,尤其是聚合前先 WHERE 过滤行数pg_stat_io(PG)或 SHOW PROFILE(MySQL)确认是否因大字段导致 read_time 异常升高当“大致准确”即可满足业务判断(如 UV 估算、长尾分布观察),硬算精确去重或分位数代价极高。PostgreSQL 的 approx_count_distinct()(需安装 hyperloglog 扩展)、MySQL 8.0+ 的 APPROX_COUNT_DISTINCT() 可将内存占用压到 KB 级,误差率通常
适用边界:
COUNT(DISTINCT user_id) 表记录超千万时,优先试 APPROX_COUNT_DISTINCT(user_id)
PERCENTILE_CONT(0.95) 在大数据集上极慢,改用 tdigest_percentile()(PG 扩展)或采样后计算按时间分区的表,如果 WHERE 条件里用了函数包裹分区键(如 WHERE DATE(created_at) = '2025-06-01'),优化器无法识别可裁剪的分区,会全表扫描所有分区——哪怕只查一天数据。
必须检查并修正:
DATE(created_at) 改成范围查询:created_at >= '2025-06-01' AND created_at
created_at::date = '2025-06-01' 同样失效)EXPLAIN 确认执行计划中出现 Partition Filter: (part_key >= ...),而非 Partition Filter: (true)
实际调优中最容易被忽略的是分区裁剪是否真正生效——它不报错、不告警,只默默让查询变慢几倍甚至几十倍。每次加新分析逻辑前,先看一眼 EXPLAIN 输出里的分区过滤项。