1

UNIONを含むクエリからページデータを返すSPがあります。これは私のDBを殺し、実行に30秒かかることがありますが、ここで明らかな何かが欠けていますか?パフォーマンスを向上させるために何ができますか?

関係するテーブル:製品、カテゴリ、カテゴリ製品

目標:カテゴリに含まれていない、またはカテゴリから削除されたすべての製品UNION現在カテゴリに含まれているすべての製品とWebサービスのページ。

参加しているすべての列にインデックスがあり、データベースには427,996の製品、6148のカテゴリ、および409,691のCategoryProductがあります。

実行に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

任意の洞察をいただければ幸いです。

4

1 に答える 1

0

あなたの状況を正しく読んだ場合、2 つの異なるクエリを持つ唯一の理由は、欠落/削除された CategoryProducts の処理です。削除されたすべての CategoryProducts を null にするためにleft join によってこの問題に対処しようとしたIsDeleted = 0ため、それらを再度テストする必要はありません。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 へのフィルターとして以外は、Category がまったく使用されていないことがわかります。この場合、2 番目の LEFT JOIN を INNER JOIN に変更し、このセクションを括弧で囲む必要があります。

于 2012-04-18T19:10:34.067 に答える