查询不使用存在语句中的索引

时间:2020-12-29 18:51:25

标签: sql sql-server tsql subquery query-optimization

我在下面的表 IDX_tbl_SpeedRun_StatusTypeID_GameID_CategoryID_LevelID_PlusInclude 上有索引 dbo.tbl_SpeedRun。下面查询中的exists语句需要一段时间(1m 10s),表示在[dbo].[tbl_SpeedRun] ([StatusTypeID],[LevelID])上缺少索引。

为什么 exists 语句没有使用我创建的索引?它已经包含 [StatusTypeID],[LevelID] 列。

表格:

CREATE TABLE [dbo].[tbl_SpeedRun] 
( 
    [OrderValue] [int] NOT NULL IDENTITY(1,1),
    [ID] [varchar] (50) NOT NULL, 
    [StatusTypeID] [int] NOT NULL,
    [GameID] [varchar] (50) NOT NULL,
    [CategoryID] [varchar] (50) NOT NULL,
    [LevelID] [varchar] (50) NULL,
    [SubCategoryVariableValues] [varchar] (1000) NULL,
    [PlayerIDs] [varchar] (1000) NULL,
    [PlatformID] [varchar] (50) NULL,
    [RegionID] [varchar] (50) NULL,
    [IsEmulated] [bit] NOT NULL,
    [Rank] [int] NULL,
    [PrimaryTime] [bigint] NULL,
    [RealTime] [bigint] NULL,
    [RealTimeWithoutLoads] [bigint] NULL,
    [GameTime] [bigint] NULL,
    [Comment] [varchar] (MAX) NULL,
    [ExaminerUserID] [varchar] (50) NULL, 
    [RejectReason] [varchar] (MAX) NULL, 
    [SpeedRunComUrl] [varchar] (2000) NOT NULL,
    [SplitsUrl] [varchar] (2000) NULL,
    [RunDate] [datetime] NULL,  
    [DateSubmitted] [datetime] NULL,   
    [VerifyDate] [datetime] NULL,   
    [ImportedDate] [datetime] NOT NULL CONSTRAINT [DF_tbl_SpeedRun_ImportedDate] DEFAULT(GETDATE()),
    [ModifiedDate] [datetime] NULL
) ON [PRIMARY] 
GO 

ALTER TABLE [dbo].[tbl_SpeedRun] 
    ADD CONSTRAINT [PK_tbl_SpeedRun] 
        PRIMARY KEY NONCLUSTERED ([ID]) WITH (FILLFACTOR=90) ON [PRIMARY] 
GO

CREATE CLUSTERED INDEX [IDX_tbl_SpeedRun_OrderValue] 
    ON [dbo].[tbl_SpeedRun] ([OrderValue]) WITH (FILLFACTOR=90) ON [PRIMARY] 
GO

CREATE NONCLUSTERED INDEX [IDX_tbl_SpeedRun_StatusTypeID_GameID_CategoryID_LevelID_PlusInclude] 
    ON [dbo].[tbl_SpeedRun] ([StatusTypeID], [GameID], [CategoryID],[LevelID]) 
       INCLUDE ([SubCategoryVariableValues], [PlayerIDs], [Rank],[PrimaryTime])
GO

查询:

SELECT 
    CASE 
       WHEN EXISTS (SELECT 1 FROM dbo.tbl_SpeedRun rn WITH (NOLOCK) 
                    WHERE rn.LevelID = l.ID AND rn.StatusTypeID = 1) 
          THEN 1 
          ELSE 0 
    END
FROM
    dbo.tbl_Level l WITH (NOLOCK)
WHERE 
    l.GameID = 'pd0wq901'
ORDER BY 
    l.OrderValue

1 个答案:

答案 0 :(得分:1)

这是子查询的 from 子句:

WHERE rn.LevelID = l.ID AND rn.StatusTypeID = 1

此谓词的有用索引将涉及任何顺序的两列。

您现有的索引不满足该要求。它有列:

[StatusTypeID], [GameID], [CategoryID], [LevelID]) 
INCLUDE ([SubCategoryVariableValues], [PlayerIDs], [Rank], [PrimaryTime])

两列都在这里,但隐藏在其他列中 - 因此数据库无法利用它来加速子查询。

底线:创建一个涉及很多列的大索引默认不会加快查询速度。相反,您可以单独分析每个查询并定义适当的优化。

相关问题