SQL事件探查器中的大量读取,但在启用统计信息时不会

时间:2015-12-15 14:19:44

标签: sql-server performance

我正在尝试解决SQL事件探查器中具有大量读取的过程,但在启用统计信息时则不行。这是一个使用分页的过程,我在第400页看到了大约17k的读取,有趣的部分是有时当我重新编译过程时,数字下降到1000-2000,如截图所示。较低的页面显示1000次读取,随着我向上移动,数字会增加:

enter image description here

在SSMS中使用SET STATISTICS IO ON显示大约1000次读取,即使Profiler说有17k:

enter image description here

这是程序的一部分(#users临时表中有4000条记录):

SELECT  [temp].[UserID] ,
            [temp].[UserName] ,
            [temp].[FirstName] ,
            [temp].[LastName] ,
            [temp].[CommissionRate] ,
            [temp].[PhotoURL] ,
            [temp].[UserStatusID] ,
            [temp].[UserStatus] ,
            [temp].[ReceivesCommission] ,
            [temp].[CreatedDateTimeUTC] ,
            [temp].[UserTypeID] ,
            [temp].[UserType] ,
            [temp].[CompanyID] ,
            [temp].[CompanyName] ,
            [temp].[CompanyLegalName] ,
            [temp].[CompanyShortName] ,
            [aggregate].[EmailAddress] ,
            [aggregate].[TelephoneCount] ,
            [aggregate].[Telephone] ,
            [aggregate].[EmailAddressCount] ,
            [address].[Address1] ,
            [address].[Address2] ,
            [address].[City] ,
            [address].[State] ,
            [address].[ZipCode]
    FROM    ( SELECT    [user].[UserID] ,
                        [user].[UserName] ,
                        [contact].[FirstName] ,
                        [contact].[LastName] ,
                        [user].[CommissionRate] ,
                        [user].[PhotoURL] ,
                        [userStatus].[UserStatusID] ,
                        [userStatus].[UserStatus] ,
                        [user].[ReceivesCommission] ,
                        [user].[CreatedDateTimeUTC] ,
                        [userType].[UserTypeID] ,
                        [userType].[UserType] ,
                        [user].[CompanyID] ,
                        [user].[CompanyName] ,
                        [user].[CompanyLegalName] ,
                        [user].[CompanyShortName]
              FROM      [#users] [user]
                        INNER JOIN [dbo].[UserStatus] [userStatus] ON [userStatus].[UserStatusID] = [user].[UserStatusID]
                        INNER JOIN [dbo].[UserType] [userType] ON [user].[UserTypeID] = [userType].[UserTypeID]
                        INNER JOIN [dbo].[Contact] [contact] ON [contact].[ContactID] = [user].[UserID]
                                                          AND [contact].[ContactTypeID] = 3
              WHERE   ( @UserName IS NULL OR [user].[UserName] LIKE '%' + @UserName + '%' )
                        AND ( @FirstName IS NULL OR [contact].[FirstName] LIKE '%' + @FirstName + '%' )
                        AND ( @LastName IS NULL OR [contact].[LastName] LIKE '%' + @LastName + '%' )
                        AND ( @CompanyID IS NULL OR [user].[CompanyID] = @CompanyID )
                        AND ( @UserStatusID IS NULL OR [user].[UserStatusID] = @UserStatusID )
              ORDER BY  [contact].[LastName] ,
                        [contact].[FirstName] ,
                        [user].[CompanyName] ,
                        [user].[UserID] DESC
                        OFFSET ( @PageNumber - 1 ) * @PageSize ROWS
              FETCH NEXT @PageSize ROWS ONLY
            ) [temp]                
            CROSS APPLY [dbo].[fnContactDetailAggregateGetByContactID]([temp].[UserID]) [aggregate]
            LEFT JOIN [dbo].[ContactAddress] [address] ON [address].[ContactID] = [temp].[UserID]

这是功能:

CREATE FUNCTION [dbo].[fnContactDetailAggregateGetByContactID]
(
  @ContactID INT
)
RETURNS @contact TABLE
(
  [ContactID] INT PRIMARY KEY NOT NULL ,
  [TelephoneCount] INT NULL ,
  [Telephone] VARCHAR(255) NULL ,
  [EmailAddressCount] INT NULL ,
  [EmailAddress] VARCHAR(255) NULL
)
WITH SCHEMABINDING 
AS
BEGIN

    INSERT  @contact
            SELECT  @ContactID ,
                    SUM(CASE WHEN [temp].[ContactDetailTypeID] = 1 THEN 1
                             ELSE 0
                        END) [TelephoneCount] ,
                    MAX(CASE WHEN [temp].[ContactDetailTypeID] = 1
                             THEN [temp].[ContactDetailValue]
                        END) [Telephone] ,
                    SUM(CASE WHEN [temp].[ContactDetailTypeID] = 3 THEN 1
                             ELSE 0
                        END) [EmailAddressCount] ,
                    MAX(CASE WHEN [temp].[ContactDetailTypeID] = 3
                             THEN [temp].[ContactDetailValue]
                        END) [EmailAddress]
            FROM    ( SELECT    [detail].[ContactID] ,
                                [label].[ContactDetailTypeID] ,
                                FIRST_VALUE([detail].[ContactDetailValue]) OVER ( PARTITION BY [label].[ContactDetailTypeID] ORDER BY [detail].[Default] DESC ) [ContactDetailValue]
                      FROM      [dbo].[ContactDetail] [detail]
                                INNER JOIN [dbo].[ContactDetailLabel] [label] ON [label].[ContactDetailLabelID] = [detail].[ContactDetailLabelID]
                      WHERE     [detail].[ContactID] = @ContactID
                    ) [temp]

    RETURN
END

任何想法可能导致这种情况以及如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

SELECT
    t.*,
    ut.[userType],
    us.[userStatus],
    g.[EmailAddress],
    g.[TelephoneCount],
    g.[Telephone],
    g.[EmailAddressCount],
    a.[Address1],
    a.[Address2],
    a.[City],
    a.[State],
    a.[ZipCode]
FROM (
SELECT
        u.*,
        c.[FirstName],
        c.[LastName],
        u.[CommissionRate],
        u.[PhotoURL],
        u.[UserStatusID],
        u.[ReceivesCommission],
        u.[CreatedDateTimeUTC],
        u.[UserTypeID],
        u.[CompanyID],
        u.[CompanyName],
        u.[CompanyLegalName],
        u.[CompanyShortName]
    FROM #users u
    JOIN dbo.contact c ON c.[ContactID] = u.[UserID] AND c.[ContactTypeID] = 3
    WHERE 
            (@UserName IS NULL OR u.[UserName] LIKE '%' + @UserName + '%')
        AND (@FirstName IS NULL OR c.[FirstName] LIKE '%' + @FirstName + '%')
        AND (@LastName IS NULL OR c.[LastName] LIKE '%' + @LastName + '%')
        AND (@CompanyID IS NULL OR u.[CompanyID] = @CompanyID)
        AND (@UserStatusID IS NULL OR u.[UserStatusID] = @UserStatusID)
    ORDER BY
        c.[LastName],
        c.[FirstName],
        u.[CompanyName],
        u.[UserID] DESC
    OFFSET (@PageNumber - 1) * @PageSize ROWS FETCH NEXT @PageSize ROWS ONLY
) t
JOIN dbo.userStatus us ON us.[UserStatusID] = u.[UserStatusID]
JOIN dbo.userType ut ON u.[UserTypeID] = ut.[UserTypeID]
CROSS APPLY (
    SELECT
        COUNT(CASE WHEN [temp].[ContactDetailTypeID] = 1 THEN 1 END) AS [TelephoneCount],
        MAX(CASE WHEN [temp].[ContactDetailTypeID] = 1 THEN [temp].[ContactDetailValue] END) AS [Telephone],
        COUNT(CASE WHEN [temp].[ContactDetailTypeID] = 3 THEN 1 END) AS [EmailAddressCount],
        MAX(CASE WHEN [temp].[ContactDetailTypeID] = 3 THEN [temp].[ContactDetailValue] END) AS [EmailAddress]
    FROM (
        SELECT
            [detail].[ContactID],
            [label].[ContactDetailTypeID],
            FIRST_VALUE([detail].[ContactDetailValue]) OVER (PARTITION BY [label].[ContactDetailTypeID] ORDER BY [detail].[default] DESC) [ContactDetailValue]
        FROM [dbo].[ContactDetail] [detail]
        JOIN [dbo].[ContactDetailLabel] [label] ON [label].[ContactDetailLabelID] = [detail].[ContactDetailLabelID]
        WHERE [detail].[ContactID] = t.[UserID]
    ) [temp]
) g
LEFT JOIN dbo.ContactAddress a ON a.ContactID = t.UserID
OPTION(RECOMPILE)