加速这个查询?目前在100K行上需要4秒

时间:2013-03-06 06:05:09

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

这是我的主要问题:

exec sp_executesql N'set arithabort off;set transaction isolation level read uncommitted;Select COUNT(*) From ( Select ROW_NUMBER() OVER 
                                (Order By  Case When d.OldInstrumentID IS NULL THEN d.LastStatusChangedDateTime Else d.RecordingDateTime End desc ) peta_rn,    
                                d.DocumentID
                                From Documents d
                                Inner Join Users u on d.UserID = u.UserID Inner Join IGroupes ig on ig.IGroupID = d.IGroupID
                                Inner Join ITypes it on it.ITypeID = d.ITypeID Where 1=1  ANd dbo.DoesNameExist(d.DocumentID, @0, @1, @2, @3) = 1  And (CreatedByAccountID = @4 
                                Or DocumentStatusID = @5
                                 Or DocumentStatusID = @6 ) )
                                  v',N'@0 int,@1 varchar(4000),@2 varchar(4000),@3 nvarchar(4000),@4 int,@5 int,@6 int',@0=-999,@1='K',@2='Miller',
                                  @3=NULL,@4=44,@5=5,@6=9

这是我的标量函数,它是罪魁祸首

ALTER FUNCTION [dbo].[DoesNameExist]
(
    @DocumentID         int,
    @PartyTypeID        int = 0,
    @FirstName          varchar(30),
    @LastName           varchar(30),
    @Business           varchar(100)
)
RETURNS bit
AS
BEGIN
    Declare @Found bit = 0

    Set @FirstName = IsNull(@FirstName,'')
    Set @LastName = IsNull(@LastName,'')
    Set @Business = IsNull(@Business,'')


    Select Top 1 @Found = 1
        From DocumentNames
            Where DocumentID = @DocumentID
                    And
                Lower(IsNull(FirstName,'')) Like 
                            Case When @FirstName = '' Then  Lower(IsNull(FirstName,'')) + '%'
                                Else Lower(@FirstName) + '%' End
                    And
                Lower(IsNull(LastName,'')) Like 
                            Case When @LastName = '' Then   Lower(IsNull(LastName,'')) + '%'
                                Else Lower(@LastName) + '%' End
                    And
                Lower(IsNull(Business,'')) Like 
                            Case When @Business = '' Then  Lower(IsNull(Business,'')) + '%'
                                Else Lower(@Business) + '%' End

                    And

                PartyTypeID = Case When @PartyTypeID IS NULL OR @PartyTypeID <= 0 Then PartyTypeID Else @PartyTypeID End


    Return @Found
END

基本上一个文档有多个DocumentNames,当用户在LastName或FirstName中键入内容时,我想带来具有这些匹配名称的所有文档的计数。请注意,我在Documents表上查询然后加入DocumentNames。这是必要的。

注意:在所有搜索列上创建索引,包括FirstName,LastName等。

谢谢!

1 个答案:

答案 0 :(得分:3)

首先,检查Execution plan

如何使用时间IsNULL()
检查所有IsNULL()的估计和实际时间。如果是更多,请使用子查询,您只需计算IsNULL()并提供给您的查询。


我没有你的Exceution plan。你也可以试试这个

ALTER FUNCTION [dbo].[DoesNameExist]
(
    @DocumentID         int,
    @PartyTypeID        int = 0,
    @FirstName          varchar(30),
    @LastName           varchar(30),
    @Business           varchar(100)
)
RETURNS bit
AS
BEGIN
    Declare @Found bit = 0

    Select Top 1 @Found = 1
        From DocumentNames
            Where DocumentID = @DocumentID
                    And
                Lower(IsNull(FirstName,'')) Like COALESCE(@FirstName,firstname,'')+'%'
                    And
                Lower(IsNull(LastName,'')) Like COALESCE(@LastName,LastName,'')+'%'
                    And
                Lower(IsNull(Business,'')) Like COALESCE(@Business,Business,'')+'%'

                    And

                PartyTypeID = Case When @PartyTypeID IS NULL OR @PartyTypeID <= 0 Then PartyTypeID Else @PartyTypeID End


    Return @Found
END

另外如果你可以放弃这个UDF,在你的EXISTS子句中直接使用它应该可以解决问题。

Select COUNT(*) From ( Select ROW_NUMBER() OVER 
                                (Order By  Case When d.OldInstrumentID IS NULL THEN d.LastStatusChangedDateTime Else d.RecordingDateTime End desc ) peta_rn,    
                                d.DocumentID
                                From Documents d
                                Inner Join Users u on d.UserID = u.UserID Inner Join IGroupes ig on ig.IGroupID = d.IGroupID
                                Inner Join ITypes it on it.ITypeID = d.ITypeID Where 1=1  



                                ANd EXISTS (
                                Select 1
                                From DocumentNames
                                    Where DocumentID = d.DocumentID
                                            And
                                        Lower(IsNull(FirstName,'')) Like COALESCE(@1,lower(firstname),'')+'%'
                                            And
                                        Lower(IsNull(LastName,'')) Like COALESCE(@2,lower(LastName),'')+'%'
                                            And
                                        Lower(IsNull(Business,'')) Like COALESCE(@3,lower(Business),'')+'%'

                                            And

                                        PartyTypeID = Case When @0 IS NULL OR @0 <= 0 Then PartyTypeID Else @0 End




                                )



                                Or DocumentStatusID = @5
                                 Or DocumentStatusID = @6 ) )
                                  v',N'@0 int,@1 varchar(4000),@2 varchar(4000),@3 nvarchar(4000),@4 int,@5 int,@6 int',@0=-999,@1='K',@2='Miller',
                                  @3=NULL,@4=44,@5=5,@6=9