我有一个SP,它返回包含UNION的查询中的分页数据。这会杀死我的数据库并且有时需要30秒才能运行,我在这里错过了一些明显的东西吗?我该怎么做才能提高它的表现?
参与的表:产品,类别,分类产品
目标: 任何不在类别中或已从类别UNION中删除的所有产品当前属于某个类别的所有产品,并通过它们覆盖网络服务。
我在所有列上都有索引,数据库中有427,996个产品,6148个类别和409,691个CategoryProducts。
这是我的查询,运行时间为6到30秒:
SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY Products.ItemID, Products.ManufacturerID) AS RowNum, *
FROM
(
SELECT Products.*,
CategoryID = NULL, CategoryName = NULL,
CategoryProductID = NULL,
ContainerMinimumQuantity =
CASE COALESCE(Products.ContainerMinQty, 0)
WHEN 0 THEN Products.OrderMinimumQuantity
ELSE Products.ContainerMinQty
END
Products.IsDeleted,
SortOrder = NULL
FROM CategoryProducts RIGHT OUTER JOIN Products
ON CategoryProducts.ManufacturerID = Products.ManufacturerID
AND CategoryProducts.ItemID = Products.ItemID
WHERE (Products.ManufacturerID = @ManufacturerID)
AND (Products.ModifiedOn > @tStamp )
AND ((CategoryProducts.IsDeleted = 1) OR (CategoryProducts.IsDeleted IS NULL))
UNION
SELECT Products.*,
CategoryProducts.CategoryID , CategoryProducts.CategoryName,
CategoryProducts.CategoryProductID ,
ContainerMinimumQuantity =
CASE COALESCE(Products.ContainerMinQty, 0)
WHEN 0 THEN Products.OrderMinimumQuantity
ELSE Products.ContainerMinQty
END
CategoryProducts.IsDeleted,
CategoryProducts.SortOrder
FROM Categories INNER JOIN
CategoryProducts ON Categories.CategoryID = CategoryProducts.CategoryID INNER JOIN
Products ON CategoryProducts.ManufacturerID = Products.ManufacturerID
AND CategoryProducts.ItemID = Products.ItemID
WHERE (Products.ManufacturerID = @ManufacturerID)
AND (Products.ModifiedOn > @tStamp OR CategoryProducts.ModifiedOn > @tStamp))
AS Products) AS C
WHERE RowNum >= @StartRow AND RowNum <= @EndRow
非常感谢任何见解。
答案 0 :(得分:0)
如果我正确地阅读了您的情况,有两个不同查询的唯一原因是对缺失/删除的CategoryProducts的处理。我试图通过左边连接IsDeleted = 0
解决这个问题,将所有已删除的CategoryProducts都置为空,所以我不必再次测试它们。 ModifiedOn部分为您想要检索的缺失/删除的Categoryproducts进行了另一个null测试。
select *
from (
SELECT
Products.*,
-- Following three columns will be null for deleted/missing categories
CategoryProducts.CategoryID,
CategoryProducts.CategoryName,
CategoryProducts.CategoryProductID ,
ContainerMinimumQuantity = COALESCE(nullif(Products.ContainerMinQty, 0),
Products.OrderMinimumQuantity),
CategoryProducts.IsDeleted,
CategoryProducts.SortOrder,
ROW_NUMBER() OVER(ORDER BY Products.ItemID,
Products.ManufacturerID) AS RowNum
FROM Products
LEFT JOIN CategoryProducts
ON CategoryProducts.ManufacturerID = Products.ManufacturerID
AND CategoryProducts.ItemID = Products.ItemID
-- Filter IsDeleted in join so we get nulls for deleted categories
-- And treat them the same as missing ones
AND CategoryProducts.IsDeleted = 0
LEFT JOIN Categories
ON Categories.CategoryID = CategoryProducts.CategoryID
WHERE Products.ManufacturerID = @ManufacturerID
AND (Products.ModifiedOn > @tStamp
-- Deleted/missing categories
OR CategoryProducts.ModifiedOn is null
OR CategoryProducts.ModifiedOn > @tStamp)
) C
WHERE RowNum >= @StartRow AND RowNum <= @EndRow
在第三次看,除了作为CategoryProducts的过滤器之外,我没有看到任何类别被使用。如果是这种情况,则应将第二个LEFT JOIN更改为INNER JOIN,并将此部分括在括号中。