为什么这个查询需要这么长时间才能执行?

Rey*_*ldi 6 performance sql-server azure-sql-database query-performance

我目前Microsoft SQL Azure (RTM) - 12.0.2000.8用作数据库。该数据库目前有 10 个 DTU。

这里的想法是我想根据视图进行查询。此视图包含SELECT()具有 5 个表连接的简单语法。该视图在大约 6 秒内给出大约 253K 行的输出。

CREATE VIEW [dbo].[TopAdsDisplaySumaryView]
AS
SELECT  
        client.Id AS ClientId,      -- (PK, int, not null)
        client.PartnerId,           -- (FK, int, not null)
        adsPict.Id AS AdsPictureId, -- (PK, int, not null)
        adsPict.ImageName,          -- (nvarchar(max), null)
        displayAds.DisplayTo,       -- (datetime, not null)
        displayAds.DisplayFrom      -- (datetime, not null)
FROM      
        dbo.Machines AS machine 
        INNER JOIN dbo.MachineGroups AS machineGroups ON machineGroups.Id = machine.MachineGroupId 
        INNER JOIN dbo.Clients AS client ON client.Id = machineGroups.ClientId 
        INNER JOIN dbo.DisplyadAds AS displayAds ON displayAds.MachineId = machine.Id 
        INNER JOIN dbo.AdsPictures AS adsPict ON adsPict.Id = displayAds.AdsPictureId
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

请注意,我仅从表clientsdisplayAds和 中获取列adsPictures,但我必须连接表machinesmachineGroupsclients. displayAdstable 拥有最多的数据。

从这里我想生成数据计数最多的前 5 个数据。这是查询:

SELECT TOP 5
    adsSum.PartnerId as PartnerId,
    adsSum.ClientId as ClientId,
    adsSum.AdsPictureId as AdsPictureId,
    adsSum.ImageName as ImageName,
    count(*) as TotalDisplay
FROM [dbo].[TopAdsDisplaySumaryView] adsSum
GROUP BY adsSum.PartnerId, adsSum.ClientId, adsSum.AdsPictureId, adsSum.ImageName
ORDER BY TotalDisplay DESC
Run Code Online (Sandbox Code Playgroud)

这是此查询的实际执行计划:https : //pastebin.com/CcR9cC5e

执行此查询时,大约需要 1 分 15 秒。我试图找出为什么这个查询需要很多时间来执行,而执行视图只需要 6 秒。

到目前为止,这是我的尝试:

  1. displayAds表创建了索引。这给了我大约 1 秒的改进,没有大的变化。

    CREATE NONCLUSTERED INDEX 
    [MachineIdIndexIncludeAdsPictureIdDisplayFromDisplayTo] ON [dbo].[DisplyadAds]
    (
        [MachineId] ASC
    )
    INCLUDE 
    (   
        [AdsPictureId],
        [DisplayFrom],
        [DisplayTo]
    )
    GO
    
    Run Code Online (Sandbox Code Playgroud)
  2. adsPictures表创建了索引。没有改变。

    CREATE NONCLUSTERED INDEX [IX_AdsPictures_IncludeImageName] ON [dbo].[AdsPictures]
    (
       [Id] ASC
    )
    INCLUDE ( [ImageName])
    GO
    
    Run Code Online (Sandbox Code Playgroud)
  3. 尝试删除adsPict.ImageName查询中的列,执行时间大大缩短至仅 3 秒(~72 秒。改进!)。我怀疑该列是问题所在,但我需要它来显示。

的最大记录长度ImageName为 36。大多在 11~20 左右。AdsPictures表中有 55 行。

知道如何解决这个问题吗?任何帮助将不胜感激。

Joe*_*ish 3

以下是我在您的实际计划的 XML 中看到的内容:

<WaitStats>
<Wait WaitType="SOS_SCHEDULER_YIELD" WaitTimeMs="66883" WaitCount="1649" />
<Wait WaitType="RESOURCE_GOVERNOR_IDLE" WaitTimeMs="56086" WaitCount="3980" />
</WaitStats>
<QueryTimeStats CpuTime="6665" ElapsedTime="73522" />
Run Code Online (Sandbox Code Playgroud)

如果您不喜欢查看 XML,您还可以在 SSMS 中计划的根节点中查看此信息:

在此输入图像描述

您可以在这里阅读有关SOS_SCHEDULER_YIELD等待的信息。一个好的外行人的解释是,您的查询只能在 CPU 上执行 6639 毫秒。它在队列上花费了 66883 毫秒等待进入 CPU。根据您对问题的描述(“执行视图只需要6秒”),您遇到的是服务器性能问题,而不是查询性能问题。当然,可能有一些方法可以使查询使用更少的 CPU,但我会通过验证服务器是否具有正确数量的 CPU 核心/DTU/其他内容并查看使用最多 CPU 的查询来解决这个问题。服务器。如果服务器上的负载较少,您的查询运行速度几乎可以提高 12 倍。