参数比例太小导致查询速度非常慢

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

我有两个表(在 Azure SQL 数据库中):

CREATE TABLE [dbo].[Action]
(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Action] [varchar](7) NOT NULL,
    [Resource] [varchar](16) NOT NULL,
    [Timestamp] [datetime] NOT NULL
)

ALTER TABLE [dbo].[Action] 
    ADD CONSTRAINT [PK_Action] 
        PRIMARY KEY CLUSTERED ([ID] ASC)

CREATE TABLE [dbo].[ResourceScope]
(
    [Resource] [varchar](16) NOT NULL,
    [Scope] [varchar](100) NOT NULL
)

ALTER TABLE [dbo].[ResourceScope] 
    ADD CONSTRAINT [PK_ResourceScope] 
        PRIMARY KEY CLUSTERED ([Scope] ASC, [Resource] ASC)

Action
表包含约 1500 万个操作,涉及约 150 万个独特资源。
ResourceScope
表包含大约 10K 行,具有独特的资源和几个不同范围之一。

API 需要使用以下查询对

Action
表进行分页,其中
<id>
<scope>
都是可变的,但页面大小始终相同。

SELECT TOP 101
    [Action].[ID], 
    [Action].[Action], 
    [Action].[Resource], 
    [Action].[Timestamp]
FROM 
    [Action] 
JOIN 
    [ResourceScope] ON [ResourceScope].[Resource] = [Action].[Resource] 
WHERE 
    [Action].[ID] <= <id>
    AND [ResourceScope].[Scope] = <scope>
ORDER BY 
    [Action].[ID] DESC

在对特定范围内的数据进行分页时,大约 95% 的查询大约需要 15 毫秒,但其余 5% 的查询需要 500 毫秒到 4000 毫秒之间的任何时间。慢速查询始终使用完全相同的 ID/范围组合,我可以将范围缩小到一些导致查询变慢的确切 ID。

查询慢的 id 与快的 id 具有完全相同的查询计划,但慢的 id 在

ResourceScope
主键上执行大量聚集索引查找,而快的 id 仅执行几次执行(主要是大约 100 次执行)该聚集索引在该索引上查找。

慢速 id 计划示例:

https://www.brentozar.com/pastetheplan/?id=ryScGHekR

快速 ID 计划示例:

https://www.brentozar.com/pastetheplan/?id=B1c6MrxyA

当我为特定范围添加索引视图(如下所示)并通过该视图进行分页时,5% 的慢查询消失了。

CREATE VIEW [dbo].[DemoSetAction]
WITH SCHEMABINDING
AS  
    SELECT
        [dbo].[Action].[ID], 
        [dbo].[Action].[Action], 
        [dbo].[Action].[Resource], 
        [dbo].[Action].[Timestamp]
    FROM 
        [dbo].[Action] 
    JOIN 
        [dbo].[ResourceScope] ON [dbo].[ResourceScope].[Resource] = dbo.[Action].[Resource] 
    WHERE 
        [dbo].[ResourceScope].[Scope] = 'demo-set'

CREATE UNIQUE CLUSTERED INDEX IDX_DemoSet ON [dbo].[DemoSetAction] (ID);

视图分页查询:

SELECT TOP 101
    [DemoSetAction].[ID], 
    [DemoSetAction].[Action], 
    [DemoSetAction].[Resource], 
    [DemoSetAction].[Timestamp]
FROM 
    [DemoSetAction] 
WHERE 
    [Action].[ID] <= <id>   
ORDER BY 
    [Action].[ID] DESC

由于可以动态添加范围(但预计不会超过约 25 个唯一范围),因此我不希望为每个范围创建索引视图。

两个问题:

  1. 查询速度慢的原因是什么?
  2. 是否可以添加/更改任何索引或其他内容,以在不使用索引视图的情况下实现相同或相似的查询性能?
sql sql-server azure-sql-database
1个回答
0
投票

为什么不在视图上创建列存储索引?

试试这个:

CREATE TABLE [dbo].[Action]
(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Action] [varchar](7) NOT NULL,
    [Resource] [varchar](16) NOT NULL,
    [Timestamp] [datetime] NOT NULL
)
GO
ALTER TABLE [dbo].[Action] 
    ADD CONSTRAINT [PK_Action] 
        PRIMARY KEY CLUSTERED ([ID] ASC);
GO
CREATE TABLE [dbo].[ResourceScope]
(
    [Resource] [varchar](16) NOT NULL,
    [Scope] [varchar](100) NOT NULL
)
GO
ALTER TABLE [dbo].[ResourceScope] 
    ADD CONSTRAINT [PK_ResourceScope] 
        PRIMARY KEY CLUSTERED ([Scope] ASC, [Resource] ASC);
GO
CREATE VIEW [dbo].[DemoSetAction]
WITH SCHEMABINDING
AS  
    SELECT
        [dbo].[Action].[ID], 
        [dbo].[Action].[Action], 
        [dbo].[Action].[Resource], 
        [dbo].[Action].[Timestamp],
        [dbo].[ResourceScope].[Scope]
    FROM 
        [dbo].[Action] 
    JOIN 
        [dbo].[ResourceScope] ON [dbo].[ResourceScope].[Resource] = dbo.[Action].[Resource] 
GO

CREATE UNIQUE CLUSTERED INDEX IDX_DemoSet ON [dbo].[DemoSetAction] (ID, [Scope]);
GO
CREATE COLUMNSTORE INDEX XC_DemoSet ON [dbo].[DemoSetAction]  ([ID], [Action], [Resource], [Timestamp], [Scope]);
GO
© www.soinside.com 2019 - 2024. All rights reserved.