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 来获得VProductFull2MajorCategoryId个 SP,第一个选择使用连接,如创建视图,第二个使用自己的视图:

-- 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返回速度更快,性能更好?为什么?还有另一种方法可以更快地获得更好VProductFullMajorCategoryId性能而不是高于 SP 吗?

4

2 回答 2

0

两者的执行时间相同,它们之间没有区别。在运行时,视图只会扩展到其底层查询。您可以通过查看这两个版本的查询计划来亲自了解这一点。

要进行优化,您需要制作VProductFull一个索引视图。意思是物化视图。然后,在从中选择时使用NOEXPAND提示。如果您想扩展有关索引视图的知识,可以在此处阅读更多内容。

如果您不想使用索引视图,请使用非索引视图,但请确保在两个表上创建两个非聚集索引: on[Pr].[Category_Id]和 on [Cat].[MajorCategory_Id]

您需要这些索引以避免聚集索引扫描,并使用更快的索引查找计划运算符。

对于第一个索引,您应该在索引中包含以下列(作为包含列,而不是索引列):[Title], [IsScanAllowed], [Id]. 对于第二个索引,您应该包括 column [Cat].[Title]

我认为您可以对两者进行试验,然后比较查询计划和执行时间(使用SET STATISTICS TIME ON.

我敢打赌,索引视图会更快,但是,如果您有大型基表,索引视图将对基表中的插入/更新产生影响。因此,您可能需要进行权衡以在所有情况下获得平衡的性能。


供参考,以及任何阅读此问题的人,请发布当前执行计划和时间以及应用每次修改后的执行计划和时间。如果这不是太麻烦的话。

于 2012-06-30T10:39:53.563 回答
0
  1. 为什么要TransactionsSelect语句中使用?

  2. 你考虑过使用SQL Profiler吗?这意味着您可以检查特定查询的Readsand 。Duration

  3. 您在子句Indexes中使用的列上有吗?Where

  4. 上面提到的View应该是Indexed View


试试下面直接在你的查询和Stored Proc比较ReadsDurationSQL 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]

根据我的理解,在这个建议中,Table Scan不会Matching records基于CategoryProduct表(这是根据 中的查询View)发生的。相反,它将仅取决于MajorCategoryTable 的单个记录。(这是根据我的建议

于 2012-06-30T11:10:21.533 回答