0

これは私の見解です:

CREATE VIEW [Products].[VProductFull] AS 
SELECT
    [Pr].[Id],
    [Pr].[Title],
    [Pr].[IsScanAllowed],
    [Pr].[Category_Id],
    [Cat].[Title] AS [Category],
    [Cat].[MajorCategory_Id],
    [Mc].[Title] AS [MajorCategory]
FROM [Products].[Product] AS [Pr]
INNER JOIN [Products].[Category] AS [Cat] ON [Pr].[Category_Id] = [Cat].[Id]
INNER JOIN [Products].[MajorCategory] AS [Mc] ON [Cat].[MajorCategory_Id] = [Mc].[Id];
GO

そして、取得するにはSPが必要です。2つのVProductFullSPMajorCategoryIdがあり、最初の1つはビューの作成などの結合を使用し、2つ目は独自のビューを使用します。

-- SP#1
CREATE PROCEDURE [Products].[GetFullProductByMajorCategory](
@MajorCategoryid            [bigint]
)
AS 
BEGIN
BEGIN TRANSACTION [FullProductByMajor]
    SELECT
        [Pr].[Id],
        [Pr].[Title],
        [Pr].[IsScanAllowed],
        [Pr].[Category_Id],
        [Cat].[Title] AS [Category],
        [Cat].[MajorCategory_Id],
        [Mc].[Title] AS [MajorCategory]
    FROM [Products].[Product] AS [Pr]
    INNER JOIN [Products].[Category] AS [Cat] ON [Pr].[Category_Id] = [Cat].[Id]
    INNER JOIN [Products].[MajorCategory] AS [Mc] ON [Cat].[MajorCategory_Id] = [Mc].[Id]
    WHERE [Mc].[Id] = @MajorCategoryid;
COMMIT TRANSACTION [FullProductByMajor]
END
GO

-- SP#2
CREATE PROCEDURE [Products].[GetFullProductByMajorCategory](
@MajorCategoryid            [bigint]
)
AS 
BEGIN
BEGIN TRANSACTION [FullProductByMajor]
    SELECT 
            [VPF].[Id],
            [VPF].[Title],
            [VPF].[IsScanAllowed],
            [VPF].[Category_Id],
            [VPF].[Category],
            [VPF].[MajorCategory_Id],
            [VPF].[MajorCategory] 
    FROM [Products].[VProductFull] AS [VPF]
    WHERE [VPF].[MajorCategory_Id] = @MajorCategoryid;
COMMIT TRANSACTION [FullProductByMajor]
END
GO

上記のSPのどれがより速く戻り、より良いパフォーマンスを持っていますか?なぜ?また、SPを超えるよりも、パフォーマンスを向上させて高速化するVProductFull別の方法はありますか?MajorCategoryId

4

2 に答える 2

0

Both have the same execution times and there will be no difference between them. At runtime the view will just be expanded to its underlying query. You can see this for yourself by looking at the query plans for both versions.

To optimize, you need to make VProductFull an indexed view. Meaning a materialized view. Then, when selecting from it use the NOEXPAND hint. If you want to extend your knowledge about indexed views, you can read more here.

If you do not want to use an indexed view, then use a non-indexed view but make sure you create two non-clustered indexes on the two tables: on [Pr].[Category_Id] and on [Cat].[MajorCategory_Id].

You need these indexes in order to avoid clustered index scans, and use the much faster index seek plan operators.

For the first index you should include the following columns in the index (as included columns, not index columns): [Title], [IsScanAllowed], [Id]. For the second index you should include column [Cat].[Title].

I think you can experiment with both and then compare the query plans as well as execution times (with SET STATISTICS TIME ON.

My bet is that the indexed view will be faster but, if you have large base tables, the indexed view will have an impact on inserts/updates in the base tables. So you may want a trade-off in order to get balanced performance in all situations.


For reference, and for whoever will read this question, please post the current execution plans and times and the ones after you apply each modification. That's if this is not too much trouble.

于 2012-06-30T10:39:53.563 に答える
0
  1. Why are you using Transactions in Select Statements?

  2. Have you considered using SQL Profiler? That means you can check the Reads and Duration for a particular Query.

  3. Do you have Indexes on the column being used in the Where clause?

  4. The above mentioned View should be Indexed View.


Try below Query directly in your Stored Proc and compare the Reads and Duration in SQL Profiler

Select 
K.[MajorCategory],
[Pr].[Id],
[Pr].[Title],
[Pr].[IsScanAllowed],
[Pr].[Category_Id],
[Cat].[Title] AS [Category],
[Cat].[MajorCategory_Id],
From
(
    Select [Title] AS [MajorCategory], [Id]
    From [Products].[MajorCategory]
    WHERE [Id] = @MajorCategoryid;
)K
INNER JOIN [Products].[Category] AS [Cat] ON [Cat].[MajorCategory_Id] = K.[Id]
INNER JOIN [Products].[Product] AS [Pr] ON [Pr].[Category_Id] = [Cat].[Id]

In this suggestion, as per my understanding, the Table Scan will not take place for all Matching records on the basis of Category and Product Table(This is as per the query in the View). It will instead depends upon merely the single record of MajorCategory Table.(This is as per my suggestion)

于 2012-06-30T11:10:21.533 に答える