语句实例(行为表 t1 与业绩表 t2 关联):
with t as (
select 行为id ,
t1.行为时间 ,
t2.用户id ,
t2.业绩时间 ,
row_number() over(partition by t1.用户id order by t1.行为时间 desc) as rnk
from 行为表 t1
join 业绩表 t2 on t1.用户id = t2.用户id and t1.行为时间 < t2.业绩时间
)
select t.行为id , t.行为时间 ,t.用户id, t.业绩时间 from t where t.rnk = 1
1、索引的优化
创建合适的索引
1-1、对 行为表 和 业绩表 中的 用户id 列创建索引,以提高 JOIN 操作的效率。
1-2、对 行为时间 和 业绩时间 列创建索引,以优化条件过滤和排序
1-3、如果查询中经常包含其他筛选条件(如 t1.行为时间 < t2.业绩时间),可以考虑使用复合索引,如 (用户id, 行为时间) 和 (用户id, 业绩时间)。
2、减少数据量
限制扫描范围
在 行为时间 和 业绩时间 之前进行过滤时,如果可以在 JOIN 前减少数据量,将大大提高性能。
SELECT t1.行为id, t1.行为时间, t2.用户id, t2.业绩时间
FROM 行为表 t1
JOIN 业绩表 t2
ON t1.用户id = t2.用户id
AND t1.行为时间 < t2.业绩时间
WHERE t2.业绩时间 > '2024-01-01';
3、减少冗余计算
3-1、避免不必要的列
在查询中只选择必要的列,避免返回不需要的列,尤其是在使用 SELECT * 时,会增加不必要的开销。
3-2、减少子查询
减少不必要的嵌套子查询或重复计算,可以通过 WITH 子句(CTE)或者窗口函数来减少计算量。
4、使用窗口函数
利用 ROW_NUMBER()、RANK() 等窗口函数可以高效地为每个用户排序并筛选出所需的数据。特别是结合 PARTITION BY 和 ORDER BY,可以减少复杂的聚合操作。
5、分区表
如果数据量非常大,可以考虑对表进行 分区(如按日期或用户 ID 分区),这样在执行查询时只需要扫描相关的分区,减少了全表扫描的开销。
6、批量操作
减少单次操作的数据量
如果你处理的数据量非常大,建议分批处理数据。通过将查询分成多个小批次执行,减少单次查询的负载,避免内存压力过大。
7、避免使用过多的 DISTINCT
如果查询结果不要求绝对去重,尽量避免使用 DISTINCT。DISTINCT 需要额外的排序步骤,会增加计算开销。
8、使用合适的 JOIN 类型
根据业务逻辑,选择合适的 JOIN 类型。避免使用不必要的 LEFT JOIN 或者 FULL JOIN
9、分析 SQL 执行计划
使用 EXPLAIN 分析 SQL 执行计划:
通过 EXPLAIN 查看数据库如何执行查询。你可以看到是否有全表扫描、是否使用了索引、关联操作的顺序等。根据这些信息,进一步调整查询。
EXPLAIN
SELECT t1.行为id, t1.行为时间,t2.用户id, t2.业绩时间
FROM 行为表 t1
JOIN 业绩表 t2
ON t1.用户id = t2.用户id
AND t1.行为时间 < t2.业绩时间;
10、并行查询
如果数据库支持并行查询(如 PostgreSQL 或 Oracle 等),可以利用多核处理器加快大数据量查询的执行时间
总结:
1、创建合适的索引,尤其是对于 用户id、行为时间 和 业绩时间 列进行单列或复合索引优化。
2、在 JOIN 之前减少数据量,通过过滤条件限制行为表中的数据行。
3、使用窗口函数优化排序和分组,避免过多的嵌套查询。
4、分析执行计划,调整索引、过滤条件及 JOIN 顺序,减少全表扫描。
标签:JOIN,t2,查询,SQL,t1,行为,id
From: https://www.cnblogs.com/qingtianyu2015/p/18424853