You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化ROW_NUMBER查询避免全表扫描的技术方案咨询

优化分组取最新记录查询的方案

针对你的场景——从31M行数据中快速获取每个id在kind_of_datetime <= 'some_value'条件下的最新一条完整记录,以下是几种无需用INCLUDE包含所有字段的优化思路:

1. 利用DISTINCT ON改写查询(PostgreSQL专属)

PostgreSQL的DISTINCT ON语法天生适配这种"分组取首条"的需求,结合你的主键结构(id, kind_of_datetime),可以直接借助主键索引快速定位数据,避免全表扫描和窗口函数的排序开销:

SELECT DISTINCT ON (id) *
FROM T0
WHERE kind_of_datetime <= 'some_value'
ORDER BY id, kind_of_datetime DESC;

主键索引本身是按id分组、kind_of_datetime排序存储的,这条查询会顺着索引遍历,每个id只取符合条件的最后一条(即kind_of_datetime最大的那条),不需要额外的排序或聚合操作,性能会大幅提升。

2. 关联子查询定位目标行(通用数据库方案)

如果你的数据库不支持DISTINCT ON,可以先通过子查询获取每个id符合条件的最大kind_of_datetime,再关联原表取出完整记录:

SELECT t0.*
FROM T0 t0
INNER JOIN (
    SELECT id, MAX(kind_of_datetime) AS max_kind
    FROM T0
    WHERE kind_of_datetime <= 'some_value'
    GROUP BY id
) t1 
    ON t0.id = t1.id 
    AND t0.kind_of_datetime = t1.max_kind;

你之前创建的索引index_name (id, kind_of_datetime DESC NULLS LAST)可以被子查询利用,快速计算每个id的最大kind_of_datetime;而主键(id, kind_of_datetime)能让关联时直接定位到对应的行,避免全表扫描。

3. 维护汇总表(高查询频率场景)

如果这个查询调用频率很高,且对实时性要求不是极端严格,可以单独维护一张汇总表,存储每个id的最新(按kind_of_datetime)完整记录:

  • 创建汇总表:
CREATE TABLE T0_latest (
    id text PRIMARY KEY,
    kind_of_datetime text,
    -- 其余10个text字段
);
  • 定时刷新(比如用 cron 或数据库定时任务):
INSERT INTO T0_latest
SELECT DISTINCT ON (id) *
FROM T0
ORDER BY id, kind_of_datetime DESC
ON CONFLICT (id) DO UPDATE SET
    kind_of_datetime = EXCLUDED.kind_of_datetime,
    -- 更新其余10个字段
;
  • 查询时直接访问汇总表:
SELECT * FROM T0_latest WHERE kind_of_datetime <= 'some_value';

这种方式把查询的开销转移到了后台刷新任务上,前端查询几乎是瞬时的,适合查询远多于写入的场景。

内容的提问来源于stack exchange,提问作者Alex Loo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 03:36:21