在 exists 语句中不使用索引的查询
Query not using index in exists statement
我在下面的 table dbo.tbl_SpeedRun
上有索引 IDX_tbl_SpeedRun_StatusTypeID_GameID_CategoryID_LevelID_PlusInclude
。下面查询中的 exists 语句需要一段时间 (1m 10s) 表示 [dbo].[tbl_SpeedRun] ([StatusTypeID],[LevelID])
.
上缺少索引
为什么 exists
语句没有使用我创建的索引?它已经包含列 [StatusTypeID],[LevelID]
.
Table:
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
这是子查询的 from
子句:
WHERE rn.LevelID = l.ID AND rn.StatusTypeID = 1
此谓词的有用索引将以任意顺序涉及两列。
您现有的索引不满足该要求。它有列:
[StatusTypeID], [GameID], [CategoryID], [LevelID])
INCLUDE ([SubCategoryVariableValues], [PlayerIDs], [Rank], [PrimaryTime])
两列都在这里,但隐藏在其他列中 - 因此数据库无法利用它来加速子查询。
底线:默认情况下,创建涉及大量列的大型索引不会加快查询速度。相反,您可以单独分析每个查询并定义适当的优化。
我在下面的 table dbo.tbl_SpeedRun
上有索引 IDX_tbl_SpeedRun_StatusTypeID_GameID_CategoryID_LevelID_PlusInclude
。下面查询中的 exists 语句需要一段时间 (1m 10s) 表示 [dbo].[tbl_SpeedRun] ([StatusTypeID],[LevelID])
.
为什么 exists
语句没有使用我创建的索引?它已经包含列 [StatusTypeID],[LevelID]
.
Table:
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
这是子查询的 from
子句:
WHERE rn.LevelID = l.ID AND rn.StatusTypeID = 1
此谓词的有用索引将以任意顺序涉及两列。
您现有的索引不满足该要求。它有列:
[StatusTypeID], [GameID], [CategoryID], [LevelID])
INCLUDE ([SubCategoryVariableValues], [PlayerIDs], [Rank], [PrimaryTime])
两列都在这里,但隐藏在其他列中 - 因此数据库无法利用它来加速子查询。
底线:默认情况下,创建涉及大量列的大型索引不会加快查询速度。相反,您可以单独分析每个查询并定义适当的优化。