我应该在哪个列上创建索引?

时间:2015-07-07 11:10:52

标签: sql-server tsql sql-server-2012

我们说我有这样的查询:

 SELECT TOP 1 doc.DocumentID 
 FROM Documents doc
 WHERE doc.JurisdictionID = cte.JurisdictionID
   AND doc.DocumentStatusID = cte.DocumentStatusID 
   AND doc.IsCourtOnly = 0
 ORDER BY LastStatusChangedDateTime

我已尝试在LastStatusChangedDateTime上创建索引,同时在DocumentID中保留JurisdictionIDDocumentStatusIDIsCourtOnlyINCLUDE 。但是性能下降,检索记录需要5秒钟。

我在这里缺少什么?

表格结构:

CREATE TABLE [dbo].[Documents](
    [DocumentID] [int] IDENTITY(1000001,1) NOT FOR REPLICATION NOT NULL,
    [IGroupID] [int] NOT NULL,
    [ITypeID] [int] NOT NULL,
    [IDate] [datetime] NULL,
    [JudgementTypeID] [smallint] NULL,
    [JurisdictionID] [int] NOT NULL,
    [DocumentDate] [smalldatetime] NULL,
    [Remarks] [varchar](256) NULL,
    [UserID] [int] NOT NULL,
    [CreatedByAccountID] [int] NULL,
    [CreatedByJurisdictionID] [int] NULL,
    [InternalNotes] [varchar](1024) NULL,
    [ParentDocumentID] [int] NULL,
    [DocumentStatusID] [tinyint] NULL,
    [FilingNumber] [int] NULL,
    [EfileDate] [datetime] NULL,
    [EfiledByUserID] [int] NULL,
    [ACEfileCreditCardID] [int] NULL,
    [ACEfileBankAccountID] [int] NULL,
    [StampData] [varchar](8000) NULL,
    [InstrumentID] [varchar](14) NULL,
    [ApprovedBy] [int] NULL,
    [RecordingDateTime] [datetime] NULL,
    [Receipt] [text] NULL,
    [ReceiptNo] [varchar](50) NULL,
    [IsReEfiled] [bit] NOT NULL,
    [OldInstrumentID] [varchar](14) NULL,
    [LastStatusChangedDateTime] [datetime] NULL,
    [ImportedFromInstrumentID] [varchar](14) NULL,
    [IsChanged] [bit] NOT NULL,
    [IsUpdatedAfterChanged] [bit] NOT NULL,
    [IsPaidInCash] [bit] NOT NULL,
    [IsPaidByCheck] [bit] NOT NULL,
    [Consideration] [money] NULL,
    [ExistingDebt] [money] NULL,
    [AssumptionBalance] [money] NULL,
    [NumberOfInstrumentPages] [smallint] NULL,
    [RecordingFee] [money] NULL,
    [AffectsRealEstate] [bit] NOT NULL,
    [FormTypeID] [tinyint] NULL,
    [IsCourtOnly] [bit] NOT NULL,
    [Fee] [money] NOT NULL,
    [IsDXRecord] [bit] NOT NULL,
    [MarriageDate] [datetime] NULL,
    [ReturnedDate] [datetime] NULL,
    [IssuedDate] [datetime] NULL,
    [IsManual] [bit] NOT NULL,
    [IsImportedViaXML] [bit] NOT NULL,
    [IsAddedViaWS] [bit] NOT NULL,
 CONSTRAINT [PK_Documents] PRIMARY KEY CLUSTERED 
(
    [DocumentID] 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] TEXTIMAGE_ON [PRIMARY]

索引:

/****** Object:  Index [IX_Documents_JurisdictionID_DocumentStatusID_IsCourtOnly]    Script Date: 7/7/2015 7:32:12 AM ******/
CREATE NONCLUSTERED INDEX [IX_Documents_JurisdictionID_DocumentStatusID_IsCourtOnly] ON [dbo].[Documents]
(
    [JurisdictionID] ASC,
    [DocumentStatusID] ASC,
    [IsCourtOnly] ASC
)
INCLUDE (   [DocumentID],
    [LastStatusChangedDateTime]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

/****** Object:  Index [IX_Documents_JurisdictionID_IGroupID]    Script Date: 7/7/2015 7:32:12 AM ******/
CREATE NONCLUSTERED INDEX [IX_Documents_JurisdictionID_IGroupID] ON [dbo].[Documents]
(
    [JurisdictionID] ASC,
    [IGroupID] ASC
)
INCLUDE (   [ITypeID],
    [UserID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

查询计划图片:

http://gyazo.com/395789526c910c973583f9bd9ef11c6f http://gyazo.com/fa2fcd2ab1ee910db2dbf1f4ff8591d2 http://gyazo.com/55385fd53c459cd0932a1247b9493732 http://gyazo.com/d6a57dcf5f18052c31968152e17bead7 http://gyazo.com/fe21d1112775f29d885a37ec24c12d3a http://gyazo.com/347d390ea799a4376385bf3de0ca298c

正如你在上一个屏幕截图中看到的那样排序占43%我在LastStatusChangedDateTime上排序所以我想在它上面创建索引但是一旦我创建上面的子查询我发布的就变得非常慢。 / p>

SQL Plan Dropbox链接:https://www.dropbox.com/s/i6dabmlqpg9y5ol/plan.sqlplan?dl=0

查询:

exec sp_executesql N';With cte as (Select *, peta_rn = ROW_NUMBER() OVER (ORDER BY LastStatusChangedDateTime desc  ) From  ( Select d.DocumentID, d.Remarks, d.IsDXRecord, EfileDate,
                                                d.IsReEfiled, d.IGroupID, d.ITypeID, d.RecordingDateTime, d.CreatedByAccountID, d.JurisdictionID, Case When d.DocumentStatusID = 9 Then d.RecordingDateTime Else d.LastStatusChangedDateTime End as 
                                                    ModifiedLastStatusChangedDateTime, it.Abbreviation as ITypeAbbreviation, ig.Abbreviation as IGroupAbbreviation,
                                                d.LastStatusChangedDateTime as LastStatusChangedDateTime
                                                ,  d.IDate, d.InstrumentID, d.DocumentStatusID
                                                , u.Username,                                                
                                                d.DocumentDate,
                                                d.OldInstrumentID, d2.Book as Book, d2.Page as Page  From Documents d   
                                Left Join Documents2 d2 On d.DocumentID = d2.DocumentID                          
                                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 ig.IGroupID > 0 And ig.Abbreviation IS NOT NULL   And d.JurisdictionID = @0  )vw ) Select cte.DocumentID, 
                                cte.IsReEfiled, cte.IGroupID, cte.ITypeID, cte.RecordingDateTime, cte.CreatedByAccountID, cte.JurisdictionID,                                 
                                cte.ModifiedLastStatusChangedDateTime, cte.Remarks, cte.IsDXRecord, cte.EfileDate,
                        cte.LastStatusChangedDateTime as LastStatusChangedDateTime
                        ,  cte.IDate, cte.InstrumentID, cte.OldInstrumentID, cte.DocumentStatusID,cte.Username, j.JDAbbreviation, inf.DocumentName,
                       cte.DocumentDate, ds.Abbreviation as DocumentStatusAbbreviation,  ds.Name as DocumentStatusName, cte.Book as Book, cte.Page as Page, 
                       ( SELECT Case When cte.DocumentStatusID = 9 Or cte.DocumentStatusID = 3 Or cte.DocumentStatusID = 6 Or cte.DocumentStatusID = 7 Or cte.DocumentStatusID = 8 Then 0 Else CAST(CASE WHEN cte.DocumentID = (
                                SELECT TOP 1 doc.DocumentID
                                FROM  Documents doc
                                WHERE doc.JurisdictionID = cte.JurisdictionID
                                        AND doc.DocumentStatusID = cte.DocumentStatusID And doc.IsCourtOnly = 0
                                ORDER BY LastStatusChangedDateTime) 
                            THEN 1
                            ELSE 0
                        END  AS BIT) End
                        ) AS CanChangeStatus, cte.ITypeAbbreviation, 
                        cte.IGroupAbbreviation,
                         (Case When (cte.IGroupID = 4 OR cte.IGroupID = 104) Then (Select Top 1 Stuff((Select '' ='' + ShortDescription from DocumentParcels dp where dp.DocumentID = cte.DocumentID FOR XML Path('''')),2,1,'''')) end) as ShortDescription,
                        (Case When (cte.IGroupID = 4 OR cte.IGroupID = 104) Then Upper((Select Stuff( (Select (Case When IsNull(cte.OldInstrumentID,'''') = '''' THEN 
        (Select  '' ,'' + ParcelldentificationNumber From ParcelJurisdictions pj Where pj.DocumentParcelID IN 
            (Select Top 100 PERCENT DocumentParcelID From DocumentParcels dp Where dp.DocumentID = cte.DocumentID Order By DocumentParcelID) 
        Order By ParcelJurisdictionAutoID For XML PATH('''')) Else (Select Top 1 Stuff((Select '' ,'' + TaxMapNumber From TaxMapNums t Where t.DocumentID = cte.DocumentID FOR XML Path('''')),1,1,'''')) End)),1,1,''''))) Else '''' End) as ParcelldentificationNumber,
        Case When (cte.IGroupID = 4 OR cte.IGroupID = 104) Then (Select Top 1 ParcelJurisdictionID From ParcelJurisdictions pj Where pj.DocumentParcelID IN 
    (Select Top 100 PERCENT DocumentParcelID From DocumentParcels dp Where dp.DocumentID = cte.DocumentID Order By DocumentParcelID) Order By ParcelJurisdictionAutoID) Else -1 End as ParcelJurisdictionID,
                        Upper((Select Top 1 Stuff( (Select ''='' + dbo.GetDocumentNameFromParamsWithPartyType(Business, FirstName, MiddleName,  LastName, t.Abbreviation, NameTypeID, pt.Abbreviation, IsGrantor, IsGrantee, dn.GenderID)  From DocumentNames dn
                                Left Join Titles t
                                    on dn.TitleID = t.TitleID               
                                Left Join PartyTypes pt
                                    On pt.PartyTypeID = dn.PartyTypeID
                                Left Join Genders gnd
                                    On gnd.GenderID = dn.GenderID
                                        Where DocumentID = cte.DocumentID
                                            For XML PATH('''')),1,1,''''))) as FlatDocumentName, (SELECT COUNT(*) FROM CTE) AS TotalRecords   FROM cte Inner Join IGroupes ig on ig.IGroupID = cte.IGroupID Inner Join ITypes it on it.ITypeID = cte.ITypeID 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>@1 AND peta_rn<=@2 Order by peta_rn',N'@0 int,@1 int,@2 int',@0=1,@1=0,@2=50

值得注意的是,这里的瓶颈是我在问题开头发布的查询:

 ( SELECT Case When cte.DocumentStatusID = 9 Or cte.DocumentStatusID = 3 Or cte.DocumentStatusID = 6 Or cte.DocumentStatusID = 7 Or cte.DocumentStatusID = 8 Then 0 Else CAST(CASE WHEN cte.DocumentID = (
                                SELECT TOP 1 doc.DocumentID
                                FROM  Documents doc
                                WHERE doc.JurisdictionID = cte.JurisdictionID
                                        AND doc.DocumentStatusID = cte.DocumentStatusID And doc.IsCourtOnly = 0
                                ORDER BY LastStatusChangedDateTime) 
                            THEN 1
                            ELSE 0
                        END  AS BIT) End
                        ) AS CanChangeStatus

如果我将其更改为1 As CanChangeStatus,我会在0秒内得到结果。如果我在LastStatusChangedDateTime上创建索引,我会在5秒内得到它,如果没有该索引,我会在2秒钟内获得。

文件主表包含约400K记录。

2 个答案:

答案 0 :(得分:2)

据我所知,您还应该在两个表中的DocumentStatusIDJurisdictionID上创建一个索引,因为在JOIN ON条件中使用了该列

WHERE doc.JurisdictionID = cte.JurisdictionID
            AND doc.DocumentStatusID = cte.DocumentStatusID

答案 1 :(得分:1)

您正在INT IDENTITY列上使用群集主键。这应该是完全没问题的。群集密钥包含所有列,并将用作其他索引的查找键。

由于你的查询中有一个“cte”,目前看不到(???)你应该知道,CTE对预过滤有很大帮助,甚至可以单独“声明”变量声明-UDF,但它们在连接中很弱。

所以 - 很可能 - 你在那里缺乏表现......

也许你最好发表整个声明?

祝你好运!

编辑:你写道这是一个“自我加入”,也许你尝试这样的事情:

SELECT TOP 1 doc.DocumentID 
 FROM Documents AS doc
 INNER JOIN Documents AS doc2 ON doc.DocumentID=doc2.DocumentID
 WHERE doc.JurisdictionID = doc2.JurisdictionID
   AND doc.DocumentStatusID = doc2.DocumentStatusID 
   AND doc.IsCourtOnly = 0
 ORDER BY doc.LastStatusChangedDateTime

编辑:您的子选择是使用CTE并且必须慢...尝试这样(对我来说这是“盲码” - 没有任何保证:-):

SELECT TOP 1 doc.DocumentID, CanChangeStatus.ChangeStatus 
 FROM Documents AS doc
 INNER JOIN Documents AS doc2 ON doc.DocumentID=doc2.DocumentID
 CROSS APPLY
 (
    SELECT CAST(
           CASE WHEN doc2.DocumentStatusID IN(9,3,6,7,8) THEN 0 
           ELSE CASE WHEN doc2.DocumentID = (
                                SELECT TOP 1 innerdoc.DocumentID
                                FROM  Documents AS innerdoc
                                WHERE innerdoc.JurisdictionID = doc2.JurisdictionID
                                        AND innerdoc.DocumentStatusID = doc2.DocumentStatusID And innerdoc.IsCourtOnly = 0
                                ORDER BY innderdoc.LastStatusChangedDateTime) 
                     THEN 1
                     ELSE 0
                END
           END AS BIT) AS ChangeStatus
) AS CanChangeStatus
 WHERE doc.JurisdictionID = doc2.JurisdictionID
   AND doc.DocumentStatusID = doc2.DocumentStatusID 
   AND doc.IsCourtOnly = 0
 ORDER BY doc.LastStatusChangedDateTime