有没有办法加速这个MSSQL 2012视图?

时间:2014-02-07 13:41:34

标签: sql-server tsql view sql-server-2012 query-optimization

以下是视图的声明:

USE [calendar2014]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE view [dbo].[AdminRegisteredCards] WITH SCHEMABINDING as 
    SELECT ISNULL(ROW_NUMBER() 
    OVER (ORDER BY ta.CreatedOn, ta.ItemId), -1000) AS AdminRegisteredCardsId,
    ta.ItemId,
    ta.CardNumber, 
    ta.FirstName, 
    ta.LastName, 
    ta.Birthday, 
    ta.PostalCode, 
    ta.[Description], 
    ta.CardActivated, 
    ta.ContactInfo, 
    ta.PhoneNumber,
    ta.ReceiveCalendarReminders, 
    ta.ReceiveGeneralMails, 
    ta.ReceivePrefStoreMails, 
    ta.CardStatus, 
    ta.SamoaCardId, 
    ta.CalendarUserId, 
    ta.LiveOpsRegistrantId,
    ta.UseType,
    ta.CreatedOn,
    ta.ModifiedBy, 
    ta.ModifiedOn 
    from (
        SELECT CalendarUser.CalendarUserId as ItemId,
        SamoaCard.CardNumber,
        SamoaCard.FirstName,
        SamoaCard.LastName,
        CalendarUser.Birthday,
        CalendarUser.PostalCode,
        RegisterSourceType.[Description],
        CalendarUserCard.CardActivated,
        CalendarUser.EmailAddress as ContactInfo,
        CalendarUser.PhoneNumber,
        CalendarUser.ReceiveCalendarReminders,
        CalendarUser.ReceiveGeneralMails,
        CalendarUser.ReceivePrefStoreMails,
        CASE WHEN CalendarUserCard.CardDeactivated IS NOT NULL THEN 'Deactivated' ELSE 'Activated' END AS CardStatus,
        SamoaCard.SamoaCardId,
        CalendarUser.CalendarUserId,
        null as LiveOpsRegistrantId,
        SamoaCard.CreatedOn,
        'C' as UseType,
        CalendarUser.ModifiedBy,
        CalendarUser.ModifiedOn 
        FROM dbo.CalendarUser CalendarUser
         INNER JOIN dbo.RegisterSourceType RegisterSourceType
          ON CalendarUser.RegisterType = RegisterSourceType.RegisterType
         INNER JOIN dbo.CalendarUserCard CalendarUserCard
          ON CalendarUserCard.CalendarUserId = CalendarUser.CalendarUserId
         INNER JOIN dbo.SamoaCard SamoaCard
          ON CalendarUserCard.SamoaCardId = SamoaCard.SamoaCardId

        UNION ALL

        SELECT LiveOpsRegistrant.LiveOpsRegistrantId as ItemId, 
            LiveOpsRegistrant.CardNumber,
            'Registered' as FirstName,
            'Card' as LastName,
            LiveOpsRegistrant.Birthday,
            null as PostalCode,
            'LiveOps' as Description,
            LiveOpsRegistrant.CreatedOn as CardActivated,
            LiveOpsRegistrant.PhoneNumber as ContactInfo,
            LiveOpsRegistrant.PhoneNumber,
            CONVERT(bit,0) as ReceiveCalendarReminders,
            CONVERT(bit,0) as ReceiveGeneralMails,
            CONVERT(bit,0) as ReceivePrefStoreMails,
            'Activated' AS CardStatus,
            SamoaCard.SamoaCardId,
            null as CalendarUserId,
            LiveOpsRegistrant.LiveOpsRegistrantId,
            SamoaCard.CreatedOn,
            'L' as UseType,
            SamoaCard.ModifiedBy,
            SamoaCard.ModifiedOn
        FROM dbo.LiveOpsRegistrant LiveOpsRegistrant
         INNER JOIN dbo.SamoaCard SamoaCard
          ON LiveOpsRegistrant.CardNumber = SamoaCard.CardNumber
    ) ta;

目前此视图的非常长时间访问 - 我们有大约140万条记录。

有没有办法优化此视图?

2 个答案:

答案 0 :(得分:0)

USE [calendar2014]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE view [dbo].[AdminRegisteredCards]


    WITH inCalender AS(
        SELECT CalendarUser.CalendarUserId as ItemId,
        SamoaCard.CardNumber,
        SamoaCard.FirstName,
        SamoaCard.LastName,
        CalendarUser.Birthday,
        CalendarUser.PostalCode,
        RegisterSourceType.[Description],
        CalendarUserCard.CardActivated,
        CalendarUser.EmailAddress as ContactInfo,
        CalendarUser.PhoneNumber,
        CalendarUser.ReceiveCalendarReminders,
        CalendarUser.ReceiveGeneralMails,
        CalendarUser.ReceivePrefStoreMails,
        CASE WHEN CalendarUserCard.CardDeactivated IS NOT NULL THEN 'Deactivated' ELSE 'Activated' END AS CardStatus,
        SamoaCard.SamoaCardId,
        CalendarUser.CalendarUserId,
        null as LiveOpsRegistrantId,
        SamoaCard.CreatedOn,
        'C' as UseType,
        CalendarUser.ModifiedBy,
        CalendarUser.ModifiedOn 
        FROM dbo.CalendarUser CalendarUser
         INNER JOIN dbo.RegisterSourceType RegisterSourceType
          ON CalendarUser.RegisterType = RegisterSourceType.RegisterType
         INNER JOIN dbo.CalendarUserCard CalendarUserCard
          ON CalendarUserCard.CalendarUserId = CalendarUser.CalendarUserId
         INNER JOIN dbo.SamoaCard SamoaCard
          ON CalendarUserCard.SamoaCardId = SamoaCard.SamoaCardId
),inLive AS(

        SELECT LiveOpsRegistrant.LiveOpsRegistrantId as ItemId, 
            LiveOpsRegistrant.CardNumber,
            'Registered' as FirstName,
            'Card' as LastName,
            LiveOpsRegistrant.Birthday,
            null as PostalCode,
            'LiveOps' as Description,
            LiveOpsRegistrant.CreatedOn as CardActivated,
            LiveOpsRegistrant.PhoneNumber as ContactInfo,
            LiveOpsRegistrant.PhoneNumber,
            CONVERT(bit,0) as ReceiveCalendarReminders,
            CONVERT(bit,0) as ReceiveGeneralMails,
            CONVERT(bit,0) as ReceivePrefStoreMails,
            'Activated' AS CardStatus,
            SamoaCard.SamoaCardId,
            null as CalendarUserId,
            LiveOpsRegistrant.LiveOpsRegistrantId,
            SamoaCard.CreatedOn,
            'L' as UseType,
            SamoaCard.ModifiedBy,
            SamoaCard.ModifiedOn
        FROM dbo.LiveOpsRegistrant LiveOpsRegistrant
         INNER JOIN dbo.SamoaCard SamoaCard
          ON LiveOpsRegistrant.CardNumber = SamoaCard.CardNumber
    ) 

    Select 
 ISNULL(ROW_NUMBER() 
    OVER (ORDER BY I.CreatedOn, I.ItemId), -1000) AS AdminRegisteredCardsId,
    I.ItemId,
    I.CardNumber, 
    I.FirstName, 
    I.LastName, 
    I.Birthday, 
    I.PostalCode, 
    I.[Description], 
    I.CardActivated, 
    I.ContactInfo, 
    I.PhoneNumber,
    I.ReceiveCalendarReminders, 
    I.ReceiveGeneralMails, 
    I.ReceivePrefStoreMails, 
    I.CardStatus, 
    I.SamoaCardId, 
    I.CalendarUserId, 
    I.LiveOpsRegistrantId,
    I.UseType,
    I.CreatedOn,
    I.ModifiedBy, 
    I.ModifiedOn 
    from inCalender I Left outer join
    inLive L on I.ItemId = L.CardNumber

注意:
  根据我的假设,我写了它。我不知道应该将哪些键用作连接的一部分。它可以相应地完成。 如果您获得任何重复记录,请不要感到惊讶,这样您就可以在select语句中添加一个distinct,或者通过适当的连接加入,这将解决问题。

答案 1 :(得分:0)

正如我在评论中提到的,如果你能告诉我这些细节,我们很乐意看一下它,看看我们是否可以进一步优化它。这里是一个较小比例的例子来说明我是如何计划用“FULL OUTER JOIN”取代“UNION ALL”

采用这种方法的原因是这只是一次选择,你不会有任何子查询。因此,不需要保留内部查询检索数据的开销,并将其传递给查询。

你可以看到我假设我的一条评论在下面的例子中是正确的,“在表SamoaCard中,没有一行会同时在SamoaCardId和CardNumber两列中都有值”

    DECLARE @CalendarUserCard TABLE
    (
        SamoaCardId INT NOT NULL
        ,name       sysname NOT NULL
    )

    DECLARE @LiveOpsRegistrant TABLE
    (
         CardNumber             INT NOT NULL
        ,LiveOpsRegistrantId    sysname NOT NULL
    )

    DECLARE @SamoaCard  TABLE
    (
        SamoaCardId     INT NULL
        ,CardNumber         INT NULL

    )

    INSERT INTO @CalendarUserCard ( SamoaCardId, name ) SELECT 1,'CalendarUserCard 1'   UNION ALL SELECT 2,'CalendarUserCard 2'
    INSERT INTO @LiveOpsRegistrant ( CardNumber, LiveOpsRegistrantId ) SELECT 3,'LiveOpsRegistrantId 3' UNION ALL SELECT 4,'LiveOpsRegistrantId 4'
    INSERT INTO @SamoaCard ( SamoaCardId,CardNumber  ) SELECT 1,NULL UNION ALL SELECT 2,NULL UNION ALL SELECT NULL,3 UNION ALL SELECT NULL,4

    SELECT * FROM @CalendarUserCard
    SELECT * FROM @LiveOpsRegistrant
    SELECT * FROM @SamoaCard

    SELECT 
        CASE 
            WHEN SamoaCard.SamoaCardId IS NULL THEN 'Value From LiveOpsRegistrant'
            WHEN SamoaCard.CardNumber IS NULL THEN 'Value From CalendarUserCard'
        END TestAttributeColumn
        ,CASE 
            WHEN SamoaCard.SamoaCardId IS NULL THEN 'Registered'
            WHEN SamoaCard.CardNumber IS NULL THEN CalendarUserCard.name
        END FirstName
        ,CASE 
            WHEN SamoaCard.SamoaCardId IS NULL THEN 'L'
            WHEN SamoaCard.CardNumber IS NULL THEN 'C'
        END UseType
        ,CASE 
            WHEN SamoaCard.SamoaCardId IS NULL THEN LiveOpsRegistrant.LiveOpsRegistrantId
            WHEN SamoaCard.CardNumber IS NULL THEN NULL
        END AS LiveOpsRegistrantId
    FROM @CalendarUserCard CalendarUserCard
    INNER JOIN @SamoaCard SamoaCard
        ON CalendarUserCard.SamoaCardId = SamoaCard.SamoaCardId
    FULL OUTER JOIN @LiveOpsRegistrant LiveOpsRegistrant
        ON SamoaCard.CardNumber = LiveOpsRegistrant.CardNumber

enter image description here