RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1024201
Accepted
Mikhail
Mikhail
Asked:2020-09-13 21:18:50 +0000 UTC2020-09-13 21:18:50 +0000 UTC 2020-09-13 21:18:50 +0000 UTC

请求或快或慢

  • 772

有一个包含 CTE 的请求。表上有必要的索引。请求第一次足够快地完成(8 秒)。此外,我想WHERE通过不在索引中的字段在 CTE(过滤数据)内添加一个部分 => 自然,查询开始工作更长时间。我看到了必要的数据,现在我想回到原来的执行(在 8 秒内),我删除了之前添加的部分WHERE,但是请求现在运行了很长时间(大约 15 分钟)并且不想滚动回到主要状态:-(

应用了什么:

  • 更新了整个数据库的统计信息 - 没有帮助。
  • 查询计划中没有“重”运算符

PS 数据没有插入到表中;无需重建索引。告诉我在哪里进一步挖掘?

SET NOCOUNT ON
DECLARE @day TABLE ([from] datetime NOT NULL, [to] datetime NOT NULL)
DECLARE @current datetime = '20190501'
WHILE @current < '20190601'
BEGIN
    INSERT INTO @day SELECT @current, DATEADD(day, 1, @current)
    SET @current = DATEADD(day, 1, @current)
END
SET NOCOUNT OFF
;WITH cte AS(SELECT
Country = 'Russia',
MacroRegion = bsp.Name,
Customer_Name = d.Name,
Contract_Number = d.ExtID,
Terminal_Device_Number = ISNULL((SELECT pc.Value
                    FROM Contact pc
                    JOIN Contact ac ON ac.Demasked_ID = pc.ID
                    WHERE ac.ID = a.Contact_ID),v_apply.Device_ID),
Service_Name  =bst.name,
StartDate=bs.firstinsert,     
EndDate = bs.lastinsert,     
Vehicle_ID=v_apply.VEHICLE_ID,
Billing_Service_ID = bs.Billing_Service_id,
Service_Type_Category=bst.Service_Type_Category,
Asid_ID = a.ID,
RenderedLastTime =(SELECT MAX(t.LastTime)
               FROM(SELECT LastTime = MAX(rsi.RenderDate)
                    FROM RenderedServiceItem rsi
                    WHERE rsi.Billing_Service_ID = bs.Billing_Service_id
                    UNION ALL
                    SELECT LastTime =(SELECT TOP (1) vltl.InsertTime
                                      FROM dbo.VEHICLE_LOG_TIME_LAST vltl 
                                      (NOLOCK)
                                      WHERE vltl.Vehicle_ID = 
                                      v_apply.VEHICLE_ID))t),
RANK() OVER(PARTITION BY  CAST (firstinsert as date),d.name  ORDER BY 
firstinsert) AS Z,
FirstInsert=bs.firstinsert
FROM Asid a 
inner join Department d  on a.Department_ID = d.DEPARTMENT_ID
inner join VEHICLE v on v.DEPARTMENT = d.DEPARTMENT_ID
left  join Billing_Service_Provider bsp  ON bsp.Billing_Service_Provider_ID 
                                            = a.Billing_Service_Provider_ID
outer APPLY (select (select top(1)  hbs.ACTUAL_TIME
                                from H_Billing_Service hbs 
                                where hbs.Asid_ID = a.ID 
                                and hbs.ACTUAL_TIME between d.[from] and d. 
                                [to]
                                order by hbs.ACTUAL_TIME asc)firstinsert,
                (select top(1)  hbs.ACTUAL_TIME
                                from H_Billing_Service hbs 
                                where hbs.Asid_ID = a.ID 
                                and hbs.ACTUAL_TIME between d.[from] and d. 
                                [to]
                                order by hbs.ACTUAL_TIME desc)lastinsert,
                (select top(1)  hbs.Billing_Service_Type_ID
                                from H_Billing_Service hbs
                                where hbs.Asid_ID=a.ID) 
                                Billing_Service_Type_ID,
                (select top(1)  hbs.ID
                                from H_Billing_Service hbs  
                                where hbs.Asid_ID = a.ID )Billing_Service_id
                from @day d         
             )bs
inner join Billing_Service_Type bst ON bst.ID = bs.Billing_Service_Type_ID

 /*Вот в этой секции началась проблема, то есть без неё было быстро, с ней 
 стало медленно. Затем после комментирования сей секции запрос снова быстро 
 отрабатывать не хочет
 and bst.Service_Type_Category in ('Group1', 'Group2', 'Group3','Group4')*/
OUTER APPLY(SELECT v.Vehicle_ID, Device_ID =  CONVERT(varchar(32), 
ci.device_id)
        FROM MLP_Controller mlpc
        right JOIN Controller c ON c.CONTROLLER_ID = mlpc.Controller_ID
        JOIN Vehicle vs ON v.VEHICLE_ID = c.VEHICLE_ID
        LEFT OUTER JOIN CONTROLLER_INFO ci ON ci.CONTROLLER_ID = 
c.CONTROLLER_ID
        WHERE v.VEHICLE_ID = vs.VEHICLE_ID) v_apply
WHERE d.IsCommercial = 1 AND  bs.firstinsert is not null
),cte2 AS
(SELECT 
cte.Country,
cte.MacroRegion,
cte.Customer_Name,
cte.Contract_Number,
cte.Terminal_Device_Number,
cte.Service_Type_Category,
cte.Service_Name,
cte.Firstinsert,
cte.StartDate,
cte.EndDate,
cte.Asid_ID,
cte.Billing_Service_ID,
cte.Z,
RenderedCount = CASE
                  WHEN cte.Service_Type_Category IN ('Group1', 'Group2', 
                  'Group3','Group4')
                  THEN
                     (SELECT [Count] = COUNT(1)
                     FROM @day d
                     WHERE EXISTS
                       (SELECT 1
                        FROM  H_Billing_Service hbs 
                        WHERE hbs.Asid_ID = cte.Asid_ID
                        AND hbs.ACTUAL_TIME BETWEEN d.[from] AND d.[to]
                        AND hbs.ACTUAL_TIME BETWEEN cte.Firstinsert AND 
                        cte.EndDate
                       )
                     )
                  ELSE 0
               END,
 LbsPositionCount =(SELECT COUNT(1)
                    FROM Position_Radius pr (NOLOCK)
                    WHERE pr.Vehicle_ID = cte.Vehicle_ID
                    AND pr.Log_Time BETWEEN DATEDIFF(ss, '1970', 
                    cte.StartDate) AND DATEDIFF(ss, '1970', cte.EndDate) 
                    AND pr.Type = 1 
                    ),
 LbsPositionRequested = (SELECT COUNT(1)
                         FROM Command c
                         WHERE c.Target_ID = cte.Vehicle_ID
                         AND c.Date_Received BETWEEN cte.StartDate AND 
                         cte.EndDate
                         AND c.Type_ID = 20 
                        ),
RenderedLastTime
FROM cte cte
where s.Z=1)
select * from cte2

执行计划: 在此处输入图像描述

sql
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    user177221
    2020-09-19T17:40:41Z2020-09-19T17:40:41Z

    从嵌套循环的数量来看,它取决于百分比(但这并不准确)。如果内存不足,可能在 IO 中。但是这个请求看起来很愚蠢,原则上不会很快起作用。

    您可以通过在请求之前执行来找出确切的内容

    SET STATISTICS TIME ON
    SET STATISTICS IO ON
    

    从输出中的服务器获取指标。测量前只应关闭实际计划。

    最有可能的是,逻辑读取的数量(由于周期,以 8 KB 页面的数量衡量)和总 CPU 时间(由于周期)将超出规模。

    查询计划中没有“重”运算符

    在此处输入图像描述

    具有如此体积的嵌套循环(箭头的粗细为数十万/百万)是非常重的运算符。他们为顶部的每一行做底部。在上图中,从红色部分开始,每行都重做蓝色部分。

    1. 断开与问题无关的部分(在注释之后)。
    2. 删除导致强制嵌套循环的所有内容 - 像 select top 1 这样的结构原则上不会很快工作。
    3. 当它工作得很快,并且计划中没有厚的嵌套循环时,返回 firstinsert / lastinsert 选择,将它们重写为窗口函数。代替循环中的一堆 select top 1,使用 FIRST_VALUE / LAST_VALUE ... PARTITION OVER (Asid_ID, CONVERT(date, ACTUAL_TIME)) 进行数百万次查询,并每天连接一次表。
    4. 重写后 - 排列 POC 索引(来自 Partition 和 Order 的列上的索引,包含聚合的值)

    如果有其他因素影响性能,请提出一个新问题。

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5