Sql server 有没有办法加快MSSQL 2012视图的速度?

Sql server 有没有办法加快MSSQL 2012视图的速度?,sql-server,tsql,view,sql-server-2012,query-optimization,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 AdminRegisteredC

以下是该视图的声明:

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万条记录

有什么方法可以优化这个视图吗

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
注:
基于我的假设,我写了它。我不知道应该作为join的一部分使用哪些键。可以据此进行。
如果您得到任何重复的记录,那么您可以在select语句中添加distinct或使用适当的join进行join,这一问题将得到解决。

正如我在评论中提到的,如果您能找到我,这些详细信息将很乐意查看,看看我们是否可以进一步优化它。在这里,我用一个小规模的例子来说明我是如何计划用“完全外部连接”取代“联合所有”的

使用这种方法的原因是,这只是一次选择,您将不会有任何子查询。这样就不会有保存内部查询检索到的数据并将其传递给外部查询的开销

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


@沙司-这不太准确。嵌套子查询可能是一个问题。如果OP使用的是新版本的SQL Server,常用表表达式可能会有所帮助。@JustinNiessner:是的,我使用的是MSSQL 2012。子句上的
连接上的额外括号不是必需的,可能会有点混淆。为什么要将
ISNULL
ROW\u NUMBER()
一起使用?并不是因为我格式化了您的代码,所以更容易看到子选项和额外选项parentheses@SergNickyvV正在谈论基础表。它们当然有模式和索引……您建议使用“左外部联接”,其中原始查询具有“Union ALL”?
    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