查询以获取跨多个表的基本统计信息会破坏我的SQL Server

时间:2011-12-29 15:05:15

标签: sql sql-server sql-server-2008

我想在我的数据库中的一堆表中进行基本的简单数据运行状况检查,以呈现给我的用户,所以我创建了这个:

SELECT
(SELECT COUNT(*) FROM StagingProducts 
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0) AS NumProducts,
(SELECT COUNT(*) FROM StagingCategories 
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0) AS NumCategories,
(SELECT COUNT(*) FROM ManufacturerSalesReps 
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0) AS NumSalesReps,
(SELECT COUNT(*) FROM Orders
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0) AS NumOrders,
(SELECT COUNT(*) FROM StagingCustomers 
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0) AS NumCustomers,
(SELECT COUNT(ItemID) As CategoryItemsCount FROM StagingCategoryItems
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
   AND ItemID NOT IN (SELECT ItemID FROM StagingProducts WHERE
                      ManufacturerID=@ManufacturerID AND IsDeleted=0)
) AS AbandonedCategoryItemsCount,
(SELECT COUNT(ChildItemID) As ChildCount FROM StagingChildItems
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
   AND ChildItemID NOT IN (SELECT ItemID FROM StagingProducts WHERE
                           ManufacturerID=@ManufacturerID AND IsDeleted=0)
) AS AbandonedChildCount,
(SELECT COUNT(RelatedItemID) As RelatedCount FROM StagingRelatedItems
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
 AND RelatedItemID NOT IN (SELECT ItemID FROM StagingProducts WHERE
                           ManufacturerID=@ManufacturerID AND IsDeleted=0)
) AS AbandonedRelatedCount,
(SELECT COUNT(TagID) As RelatedCount FROM StagingTags
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
   AND ItemID NOT IN (SELECT ItemID FROM StagingProducts WHERE
                      ManufacturerID=@ManufacturerID AND IsDeleted=0)
) AS AbandonedTagCount,
(SELECT COUNT(ItemID) As ModifierItemCount FROM StagingProductModifierLists
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
 AND ItemID NOT IN (SELECT ItemID FROM StagingProducts WHERE
                    ManufacturerID=@ManufacturerID)
) As AbandonedModifierItemCount,
(SELECT COUNT(*) FROM
   (SELECT COUNT(*) AS CNT, CustomerNumber FROM StagingCustomers
    WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
    GROUP BY CustomerNumber HAVING COUNT(*) > 1
   ) AS DuplicateCustomerCount
) AS DuplicateCustomerCount,
(SELECT COUNT(*) FROM 
   (SELECT COUNT(*) AS CNT, ItemID FROM StagingProducts
    WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0
    GROUP BY ItemID HAVING COUNT(*) > 1
   ) AS DuplicateItemCount
) AS DuplicateItemCount

这有时可以超快速运行,但在其他时候只是挂起服务器。对于我来说,将几个表中的数据转换为单个查询的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

由于您在数据库中触摸了这么多表,并且在运行查询时可以使用这些表中的任何一个,如果从表中获取绝对最新信息并不是非常重要,我会使用

ALTER PROCEDURE [dbo].[WebManager_DataHealth] @ManufacturerID INT 
AS 
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT .....
END

答案 1 :(得分:0)

作为识别问题的第一步,我建议将每个子查询分开并选择它们之间的当前日期和时间 - 如下所示:

select getdate()

SELECT COUNT(*) AS NumProducts FROM StagingProducts 
WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0

select getdate()

SELECT COUNT(*) AS NumCategories FROM StagingCategories 
WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0

...

这可以让您识别哪些是有问题的查询。 (如果这是由对数据库资源的同时需求太多引起的,可能会减少问题。)

作为第二步,我会考虑将NOT IN子查询重构为NOT EXISTS子查询 - 如下所示:

SELECT COUNT(ItemID) As CategoryItemsCount FROM StagingCategoryItems sci
 WHERE ManufacturerID=@ManufacturerID AND IsDeleted=0 AND NOT EXISTS 
       (SELECT NULL FROM StagingProducts sp WHERE sp.ItemID = sci.ItemID and 
        ManufacturerID=@ManufacturerID AND IsDeleted=0)

虽然我发现这种类型的重构可以提高性能,但我强烈建议您检查NOT EXISTS和NOT IN表单的运行时间 - 情况可能会有所不同。

我还建议检查有问题(即长时间运行)查询的查询计划,检查相关表上的索引是否正确使用,以及新索引是否可以提高性能。