1

使用带有外部应用的视图时,我看到一些奇怪的查询速度结果,我对视图中的 2 个不同列进行了不同的计数,1 个在不到 0.1 秒内完成,另一个需要 4-6 秒,是第二个计数查询返回较慢,因为它是外部应用的一部分?如果是这样 - 我怎样才能加快这个查询?

快速不同的计数是 -

SELECT DISTINCT ISNULL([ItemType], 'N/A') AS Items FROM vwCustomerItemDetailsFull

缓慢的不同计数是 -

SELECT DISTINCT ISNULL([CustomerName], 'N/A') AS Items FROM vwCustomerItemDetailsFull

观点是——

SELECT I.ItemID,
       IT.Name AS ItemType,
       CASE
         WHEN CustomerItemEndDate IS NULL
               OR CustomerItemEndDate > GETDATE() THEN CustomerItems.CustomerName
         ELSE NULL
       END     AS CustomerName,
       CASE
         WHEN CustomerItemEndDate IS NULL
               OR CustomerItemEndDate > GETDATE() THEN CustomerItems.CustomerNumber
         ELSE NULL
       END     AS CustomerNumber,
       CASE
         WHEN CustomerItemEndDate IS NULL
               OR CustomerItemEndDate > GETDATE() THEN CustomerItems.CustomerItemStartDate
         ELSE NULL
       END     AS CustomerItemStartDate,
FROM   tblItems I
       INNER JOIN tblItemTypes IT
         ON I.ItemTypeID = IT.ItemTypeID
       OUTER APPLY (SELECT TOP 1 CustomerName,
                                 CustomerNumber,
                                 StartDate AS CustomerItemStartDate,
                                 EndDate   AS CustomerItemEndDate
                    FROM   tblCustomerItems CI
                           INNER JOIN tblCustomers C
                             ON C.CustomerID = CI.CustomerID
                    WHERE  CI.ItemID = I.ItemID
                    ORDER  BY EndDate DESC) AS CustomerItems 
4

1 回答 1

3

检查执行计划,这个速度差异一点也不奇怪,因为它是外部应用而不是交叉应用,并且在其中您将结果限制为top 1,这意味着您的外部应用对数量没有影响查询的结果或列ItemType

因此,当您从视图中选择并且不使用外部应用中的任何列时,优化器足够聪明,知道它不需要执行它。所以本质上你的第一个查询是:

SELECT  DISTINCT ISNULL([ItemType], 'N/A') AS Items
FROM    (   SELECT  tblItems
            FROM    Items
                    INNER JOIN tblItemTypes IT 
                        ON I.ItemTypeID = IT.ItemTypeID
        ) vw

而您的第二个查询必须执行外部应用。

我之前发布了一个更长的答案,这也可能会有所帮助。

编辑

如果您想将查询更改为 JOIN 它可以重写为:

SELECT I.ItemID,
        IT.Name AS ItemType,
        CustomerName,
        CustomerNumber,
        CustomerItemStartDate,
FROM   tblItems I
        INNER JOIN tblItemTypes IT
            ON I.ItemTypeID = IT.ItemTypeID
        LEFT JOIN
        (   SELECT  ci.ItemID,
                    CustomerName,
                    CustomerNumber,
                    StartDate AS CustomerItemStartDate,
                    EndDate   AS CustomerItemEndDate,
                    RN = ROW_NUMBER() OVER (PARTITION BY ci.ItemID ORDER BY EndDate DESC)
            FROM    tblCustomerItems CI
                    INNER JOIN tblCustomers C
                        ON C.CustomerID = CI.CustomerID
        ) AS CustomerItems 
            ON CustomerItems.ItemID = I.ItemID
            AND CustomerItems.rn = 1
            AND CustomerItems.CustomerItemEndDate  < GETDATE();

但是,我认为这不会大大提高性能,因为您说最昂贵的部分是 sort on EndDate,并且对于您的第一个查询,它将对性能产生负面影响,因为优化器将不再优化外部应用。

我希望提高性能的最佳方法是添加索引,而不知道您的数据大小或分布我无法准确猜测您需要的确切索引,如果您自己运行查询,显示实际执行计划 SSMS 将建议给你的索引,这比我最好的猜测要好。

于 2013-06-25T15:30:54.447 回答