优化SQL查询:在visitor_id分组内获取c_id≠0行之后的连续记录
SQL优化思路及优化后示例
原SQL核心问题为重复扫描目标表、重复计算窗口函数,存在大量冗余计算,优化思路如下:
- 消除重复表扫描:原SQL累计3次扫描目标表,可通过CTE提前抽取所需的全量数据集,统一计算一次行号后供后续逻辑复用,避免重复IO开销。
- 简化关联逻辑:原SQL通过JOIN关联起始行号的方式可以替换为窗口函数直接计算每个
visitor_id分组的起始行,无需额外分组聚合再关联,减少计算步骤。 - 简化冗余子查询:原逻辑中筛选符合条件的
visitor_id时嵌套了多余的子查询,可直接合并过滤条件,仅查询所需的visitor_id字段即可,无需读取全量字段。 - 索引优化:创建
(visitor_id, date, c_id)联合覆盖索引,可同时命中分区排序、过滤条件,窗口函数计算行号时无需额外排序,也无需回表查询数据,大幅提升执行效率。
优化后SQL示例
WITH base_data AS ( -- 一次性提取所需数据,统一计算行号和分组起始行 SELECT *, ROW_NUMBER() OVER (PARTITION BY visitor_id ORDER BY date) AS rn, -- 计算每个visitor_id分组中第一个c_id≠0的行号 MIN(CASE WHEN c_id != 0 THEN rn END) OVER (PARTITION BY visitor_id) AS start_rn FROM "DB"."schema"."table" WHERE date >= '2021-08-01' AND date <= '2021-08-30' AND visitor_id IN ( -- 简化后的符合条件的visitor_id查询 SELECT DISTINCT visitor_id FROM "DB"."schema"."table" WHERE date >= '2021-08-01' AND date <= '2021-08-30' AND c_id = '101' ) ) -- 过滤得到起始行之后的所有数据,可根据需求调整返回字段 SELECT * EXCLUDE (rn, start_rn) FROM base_data WHERE rn >= start_rn
注:若所用数据库不支持
EXCLUDE语法,手动列出需要返回的业务字段即可,避免返回rn、start_rn等辅助计算字段。
内容的提问来源于stack exchange,提问作者Cks
相关产品推荐
相关产品推荐

