这是我的疑问:
exec sp_executesql N'set arithabort off;set statistics time on; set transaction isolation level read uncommitted;With cte as (Select peta_rn = ROW_NUMBER() OVER (ORDER BY d.LastStatusChangedDateTime desc )
, d.DocumentID,
d.IsReEfiled, d.IGroupID, d.ITypeID, d.RecordingDateTime, d.CreatedByAccountID, d.JurisdictionID,
d.LastStatusChangedDateTime as LastStatusChangedDateTime
, d.IDate, d.InstrumentID, d.DocumentStatusID
, u.Username
, it.Abbreviation AS ITypeAbbreviation
, ig.Abbreviation AS IGroupAbbreviation,
d.DocumentDate
From Documents d
Inner Join ITypes it on it.ITypeID = d.ITypeID
Inner Join Users u on d.UserID = u.UserID Inner Join IGroupes ig on ig.IGroupID = d.IGroupID
Where 1=1 And ( d.DocumentStatusID = 9 ) ) Select cte.DocumentID,
cte.IsReEfiled, cte.IGroupID, cte.ITypeID, cte.RecordingDateTime, cte.CreatedByAccountID, cte.JurisdictionID,
cte.LastStatusChangedDateTime as LastStatusChangedDateTime
, cte.IDate, cte.InstrumentID, cte.DocumentStatusID,cte.IGroupAbbreviation, cte.Username, j.JDAbbreviation, inf.DocumentName,
cte.ITypeAbbreviation, cte.DocumentDate, ds.Abbreviation as DocumentStatusAbbreviation, ds.Name as DocumentStatusName,
( SELECT CAST(CASE WHEN cte.DocumentID = (
SELECT TOP 1 doc.DocumentID
FROM Documents doc
WHERE doc.JurisdictionID = cte.JurisdictionID
AND doc.DocumentStatusID = cte.DocumentStatusID
ORDER BY LastStatusChangedDateTime)
THEN 1
ELSE 0
END AS BIT)
) AS CanChangeStatus ,
Upper((Select Top 1 Stuff( (Select ''='' + dbo.GetDocumentNameFromParamsWithPartyType(Business, FirstName, MiddleName, LastName, t.Abbreviation, NameTypeID, pt.Abbreviation, IsGrantor, IsGrantee) From DocumentNames dn
Left Join Titles t
on dn.TitleID = t.TitleID
Left Join PartyTypes pt
On pt.PartyTypeID = dn.PartyTypeID
Where DocumentID = cte.DocumentID
For XML PATH('''')),1,1,''''))) as FlatDocumentName, (SELECT COUNT(*) FROM CTE) AS TotalRecords
FROM cte Left Join DocumentStatuses ds On
cte.DocumentStatusID = ds.DocumentStatusID Left Join InstrumentFiles inf On cte.DocumentID = inf.DocumentID
Left Join Jurisdictions j on j.JurisdictionID = cte.JurisdictionID Where 1=1 And
peta_rn>@7 AND peta_rn<=@8 Order by peta_rn set statistics time off; ',N'@0 int,@1 int,@2 int,@3 int,@4 int,@5 int,@6 int,@7 int,@8 int',
@0=1,@1=5,@2=9,@3=1,@4=5,@5=9,@6=1,@7=97500,@8=97550
这是我的IGroupes表定义:
CREATE TABLE [dbo].[IGroupes](
[IGroupID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](64) NOT NULL,
[JurisdictionID] [int] NOT NULL,
[Abbreviation] [varchar](12) NOT NULL,
CONSTRAINT [PK_IGroupes] PRIMARY KEY NONCLUSTERED
(
[IGroupID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
SET ANSI_PADDING ON
GO
/****** Object: Index [IX_IGroupes_Abbreviation] Script Date: 10/11/2013 4:21:46 AM ******/
CREATE NONCLUSTERED INDEX [IX_IGroupes_Abbreviation] ON [dbo].[IGroupes]
(
[Abbreviation] ASC
)
INCLUDE ( [IGroupID],
[Name],
[JurisdictionID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
/****** Object: Index [IX_IGroupes_JurisdictionID] Script Date: 10/11/2013 4:21:46 AM ******/
CREATE NONCLUSTERED INDEX [IX_IGroupes_JurisdictionID] ON [dbo].[IGroupes]
(
[JurisdictionID] ASC
)
INCLUDE ( [IGroupID],
[Name],
[Abbreviation]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
/****** Object: Index [IX_IGroupes_Name] Script Date: 10/11/2013 4:21:46 AM ******/
CREATE NONCLUSTERED INDEX [IX_IGroupes_Name] ON [dbo].[IGroupes]
(
[Name] ASC
)
INCLUDE ( [IGroupID],
[JurisdictionID],
[Abbreviation]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
然而,请看它正在使用表扫描。这个操作让我付出太多代价。 IGroupes
表只有7行,Documents
表有大约98K的记录。然而,当我加入d.IGroupID = ig.IGroupID
时,它会显示超过600K的实际行数!那就是问题所在。请参阅随附的屏幕截图:
如果有人对完整的查询计划xml感兴趣,那么它是:
https://www.dropbox.com/s/kldx24x3j8vndpe/plan.xml
感谢任何帮助。谢谢!
答案 0 :(得分:2)
在这种情况下,表扫描可能比使用IGroupes
表上的任何索引更有效。
如果您认为表扫描操作是此查询的瓶颈(虽然成本为3%,我不确定),您可以尝试修改PK_IGroupes
成为聚簇索引,也可以尝试像
CREATE UNIQUE NONCLUSTERED INDEX [IX_IGroupes_IGroupID]
ON [dbo].[IGroupes] ([IGroupID]) INCLUDE ([Abbreviation])
答案 1 :(得分:2)
IGroupes
上的3个索引(PK除外)都没有帮助此查询,因为您没有在where或join子句中使用任何这些字段。除非您需要其他查询的索引,否则我会删除它们。它们只是为查询优化器提供了更多的选择来测试(和拒绝)。
主键PK_IGroupes
上的索引应该是群集的。这将允许它进行索引搜索(或书签查找)。如果由于其他原因无法对其进行群集,请尝试按此顺序在IGroupID
和Abbreviation
上创建索引(或在现有PK索引中包含Abbreviation
列)。< / p>
如果它仍然没有选择正确的索引,您可以使用WITH(INDEX(0))
或WITH(INDEX('index-name'))
等提示。
600k行的确来自于它在98k行上乘以7行进行嵌套循环连接。如果上述索引不起作用,您可以尝试将INNER JOIN iGroupes
替换为INNER HASH JOIN IGroupes
。