2015-12-15 9 views
1

我试图排除SQL事件探查器中读取次数高的过程,但不启用统计信息时。这是一个使用分页的过程,例如,我在第400页上看到了大约17k次读取,有趣的部分是有时当我重新编译过程时,数字会降至1000-2000,如您在屏幕截图中所看到的。下页显示为我动了千读取,与越聚越多:在SQL事件探查器中读取的次数很多,但在启用统计信息时没有。

enter image description here

SSMS中使用SET STATISTICS IO ON显示大约1000个读数,即使探查说,有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 

任何想法可能是造成这一点,我怎么能去修复它?

+0

请为'fnContactDetailAggregateGetByContactID'提供ddl – Devart

+0

我已将它添加到帖子中。谢谢! – user3800174

回答

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) 
+0

那么你认为这是导致读取次数很多的函数吗?我想以某种方式保持它的独立性,因为我需要在另外7个程序中提取电话号码和电子邮件。 – user3800174

+0

我想是的...只是尝试此代码并提供结果。 – Devart

+0

好吧,所以在程序中添加交叉应用程序,我看到1500左右的读取。有关如何将其移回到程序中的任何想法?我已经尝试了一个观点,并且也获得了低于标准的结果。 – user3800174

相关问题