SQL查询因自定义列Data_hora_Saida运行缓慢,求性能优化方案
性能问题根因
当前使用的关联子查询会为外层查询返回的每一行单独执行一次视图扫描,数据量越大性能损耗越严重,这就是Data_hora_Saida列拖慢查询速度的核心原因。
优化方案
改用窗口函数一次性完成全量计算,无需逐行二次查询,性能提升非常明显:
WITH all_record AS ( SELECT ID_acesso, data_hora, data, Sentido, Unidade, REPLACE(REPLACE(Documento,'.',''),'-', '') AS Documento, Tipo_Documento, Nome, Tipo_Usuario, Categoria, Empresa_Usuario, Visitado, Tipo_Documento_Visitado, -- 匹配同证件、同证件类型下,当前记录之后最早的离场时间 MIN(CASE WHEN Sentido = 'Saída' THEN data_hora END) OVER ( PARTITION BY Documento, Tipo_Documento ORDER BY data_hora, ID_acesso ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) AS Data_hora_Saida FROM Ses.dbo.VIEW_Man_Dashboard_BI WHERE data >= CONVERT(DATE,'2021-10-01') AND Empresa_Usuario != 'CAMPSEG' AND Sentido IN ('Entrada', 'Saída') ) SELECT ID_acesso, data_hora AS Data_Hora_Entrada, data AS Data_Entrada, Sentido, Unidade, Documento, Tipo_Documento, Nome, Tipo_Usuario AS Tipo_Usuario, Categoria AS Tipo_Pessoa, Empresa_Usuario, Visitado, Tipo_Documento_Visitado, Data_hora_Saida FROM all_record WHERE Sentido = 'Entrada' ORDER BY Unidade, Data_Hora_Entrada;
提示:如果你使用的是SQL Server 2022及以上版本,可以用更简洁的
LEAD函数写法实现相同逻辑:LEAD(CASE WHEN Sentido = 'Saída' THEN data_hora END) IGNORE NULLS OVER ( PARTITION BY Documento, Tipo_Documento ORDER BY data_hora, ID_acesso ) AS Data_hora_Saida另外注意你原查询中子查询引用的视图名为
VIEW_Mand_Dashboard_BI,外层为VIEW_Man_Dashboard_BI,如果不是笔误请自行调整视图名称。
额外性能优化建议
- 给视图依赖的底层表创建联合索引:
(Sentido, data, Empresa_Usuario, Documento, Tipo_Documento),并包含查询用到的其他字段,避免回表开销。 - 如果
VIEW_Man_Dashboard_BI是多层嵌套的视图,优先优化视图内部的关联逻辑,移除不必要的表连接和计算。
内容的提问来源于stack exchange,提问作者Fernando Fefu
相关产品推荐
相关产品推荐

