如何优化查询?

问题描述 投票:0回答:1

我有一个运行 6 分钟的 T-SQL 查询。

其中同一个表有多个子查询。我认为这是问题的原因。 但我不知道如何优化它。

SELECT  dateheure, bac, presence, reponse
    ,(select top 1 dateheure from LogEvents where bac = t1.bac and dateheure < t1.dateheure order by id desc) as dateheure_precedente
    ,(select top 1 presence from LogEvents where bac = t1.bac and dateheure < t1.dateheure order by id desc) as presence_precedente 
    ,(select top 1 reponse from LogEvents where bac = t1.bac and dateheure < t1.dateheure order by id desc) as reponse_precedente   
    ,(select top 1 dateheure from LogEvents where bac = t1.bac and dateheure > t1.dateheure order by id asc) as dateheure_suivante
    ,(select top 1 presence from LogEvents where bac = t1.bac and dateheure > t1.dateheure order by id asc) as presence_suivante
    ,(select top 1 reponse from LogEvents where bac = t1.bac and dateheure > t1.dateheure order by id asc) as reponse_suivante
FROM [alpla_log].[dbo].[LogEvents] t1 
WHERE 
    t1.presence = 7845
    AND dateheure BETWEEN '11/07/2024 00:00:00' AND '11/07/2024 23:59:59.997' 
ORDER BY id DESC

唯一使用的表是“LogEvents”

CREATE TABLE LogEvents (
    id int IDENTITY NOT NULL PRIMARY KEY,
    dateheure datetime NULL,
    type varchar(50) NULL,
    msg varchar(MAX) NULL,
    presence int NULL,
    destination int NULL,
    status_prt int NULL,
    reponse int NULL,
    bac int NULL
);

您可以在这里找到执行计划。

我尝试在表上添加索引,但没有什么区别。

CREATE NONCLUSTERED INDEX ON dbo.Logevents (bac, dateheure) INCLUDE (reponse)

没有其他索引。

该表是自动化仓库中的事件日志。它保存了盒子在不同地方的位置。我想找到每个盒子与特定位置相比的上一个和下一个位置。

sql-server t-sql query-optimization
1个回答
0
投票

您的查询可以得到显着改善。

  • 虽然您可以用两个
    APPLY
    替换六个子查询,但更好的解决方案是使用
    LEAD
    LAG
    窗口函数。
  • WHERE
    子句不是“可管理的”(不能使用索引)。相反,使用日期范围,最好是半开区间
    >= AND <
  • 如果不是绝对必要,请删除
    ORDER BY
    ,因为它与
    WHERE
    PARTITION BY
    LEAD
    的顺序不同。
SELECT
  dateheure,
  bac,
  presence,
  reponse,
  LAG(t1.dateheure) OVER (PARTITION BY t1.bac ORDER BY t1.dateheure) as dateheure_precedente,
  LAG(t1.presence ) OVER (PARTITION BY t1.bac ORDER BY t1.dateheure) as presence_precedente,
  LAG(t1.reponse  ) OVER (PARTITION BY t1.bac ORDER BY t1.dateheure) as reponse_precedente,
  LEAD(t1.dateheure) OVER (PARTITION BY t1.bac ORDER BY t1.dateheure) as dateheure_suivante,
  LEAD(t1.presence ) OVER (PARTITION BY t1.bac ORDER BY t1.dateheure) as presence_suivante,
  LEAD(t1.reponse  ) OVER (PARTITION BY t1.bac ORDER BY t1.dateheure) as reponse_suivante
FROM LogEvents t1 
WHERE 
    t1.presence = 7845
    AND dateheure >= '20240711'
    AND dateheure < '20240712';

最后添加正确的索引来支持此查询。

CREATE INDEX IX ON LogEvents (presence, bac, dateheure) INCLUDE (reponse);

您可以从这个小提琴中看到,这现在会导致基表的单次扫描,没有连接,没有键查找,也没有排序。

© www.soinside.com 2019 - 2024. All rights reserved.