2017-04-20 8 views
2

Ich habe eine Ansicht, die ungefähr 1 Million Zeilen abfragt und ca. 10-15 Minuten benötigt, um die Ausführung abzuschließen. Ich möchte Clusterindizierung bereitstellen, damit sie physisch existiert Schema und dauert weniger Zeit zu laden, aber es gibt eine Reihe von Einschränkungen, um Clusterindizierung, dh nur INNER JOIN sind erlaubt und keine Unterabfragen sollte in Ansichten Definition vorhanden sein, wie ich die LINKE JOIN in dieser Ansicht mit INNER JOIN ersetzen und wie beseitige ich Unterabfragen aus dieser Definition von Sichten, damit die Cluster-Indizierung darauf angewendet werden kann.Anwenden der Clusterindizierung auf eine Ansicht in SQL Server 2012

CREATE view [dbo].[FTM_ProfileDetailsView] with SCHEMABINDING as 

    select FTM.Id 
    , FTM.EmployeeId 
    , FTM.CustomerId 
    , FTM.AbsenceFirstDate 
    , FTM.BackgroundHistory 
    , FTM.BackgroundHistoryComments 
    , FTM.IsEmployeeAbsent,FTM.ServiceId 
    , Case When isnull(FTM.IsSelfManagement,'')='' THEN cast(0 as bit) ELSE FTM.IsSelfManagement END as IsSelfManagement 
    , PR.ServiceLineId,FTM.ProfileId,PR.StatusId,Status.Status as StatusName 
    , PR.ReasonID 
    , PR.ModifiedDate 
    , PR.WithdrawnReason 
    , PR.CreatedBy 
    , PR.CreatedDate 
    , PR.IsActive 
    , mgrs.usernames as LineManagers 
    , cust.CustomerName 
    , ltrim(rtrim(emp.EmployeeTitle+' '+ emp.FirstName+' '+ emp.Surname)) as EmployeeFullName 
    , FTM.ProfileManagerId 
    , FTM.IsProfileManagement 
    , AM.MonitoringChecks 
    , AM.Frequency 
    , AM.ProfileManagerNotes 
    , AM.TaskDateAndTime 
    , FTM.ProfileManagementCriteriaId 
    ,cast(case when PR.StatusId = 13 then 1 else 0 end as bit) as IsActiveMonitoring 
    , CustServ.CustomerServiceName 
    , BU.Name as BusinessUnit 
    , emp.DASID 
    , emp.DateOfBirth as EmployeeDOB 
    , addr.PostCode 
    , coninfo.Email 
    , (select top 1 
     StatusId from dbo.PR_Profileintervention ProfileInt 
     where ProfileInt.ProfileId=FTM.Profileid 
     order by ProfileInt.Id desc) as LatestInterventionStatusId 
    , (select name from dbo.FTM_Intervention Intr 
     where Intr.Id=(select top 1 InterventionId from dbo.PR_Profileintervention ProfileInt 
     where ProfileInt.ProfileId=FTM.Profileid 
     order by ProfileInt.Id desc)) 
     as LatestInterventionName from FTM_Profile FTM 

    LEFT JOIN dbo.ProfileManagersView mgrs ON mgrs.ProfileID = FTM.ProfileID 
    INNER JOIN dbo.Customer cust on cust.Id= FTM.CustomerId 
    INNER JOIN dbo.Employee emp on emp.Id = FTM.EmployeeId 
    INNER JOIN dbo.PR_Profile PR on PR.Profileid=FTM.ProfileId 
    LEFT JOIN dbo.BusinessUnit BU on BU.Id=PR.BUId 
    LEFT JOIN dbo.PR_dv_Status [Status] on [Status].Id = PR.StatusId 
    LEFT JOIN dbo.CM_ActiveMonitoringDetails AM on AM.ProfileId = PR.Profileid 
    LEFT JOIN dbo.FTM_CustomerServiceMapping CustServ on CustServ.ServiceId = FTM.ServiceId and CustServ.CustomerId = FTM.CustomerId 
    LEFT JOIN dbo.contact con on con.Id = emp.ContactID 
    LEFT JOIN dbo.address addr on addr.Id = con.HomeAddressId 
    LEFT JOIN dbo.contactinfo coninfo on coninfo.Id = con.ContactInfoId 
+0

[Hier starten] (https://docs.microsoft.com/en-us/sql/relational-databases/views/create-indexed-views) –

+0

@ ZoharPeled Ich habe es gelesen, mein Problem ist, wie diese Einschränkungen in meinen Ansichten zu überwinden sind. –

+0

Es gibt keine magische "Schalter" X "für" Y "und Schalter" W "für" Z "", um diese Einschränkungen zu überwinden. Wenn es welche gäbe, warum würde das Produkt sie dann nicht automatisch für Sie tun? Wenn die ursprüngliche Abfrage vernünftig konstruiert ist, aber eine Begrenzung erreicht, trifft im Allgemeinen jede normale Neuschreibung der Abfrage die gleichen oder andere Einschränkungen. –

Antwort

1

Ich habe einen Vorschlag. Können Sie versuchen, Ihre Abfrage zu ändern, damit die Unterabfragen in SELECT in CROSS APPLYs platziert werden?

So etwas entlang der Linien von dieser in Ihrem WHERE-Klausel:

CROSS APPLY ( 
       select top 1 StatusId AS LatestInterventionStatusId 
       from dbo.PR_Profileintervention ProfileInt 
       where ProfileInt.ProfileId=FTM.Profileid 
       order by ProfileInt.Id desc 

      ) LatestInterventionStatusId 

CROSS APPLY (
       select name AS LatestInterventionName 
       from dbo.FTM_Intervention Intr 
       where Intr.Id=(select top 1 InterventionId 
           from dbo.PR_Profileintervention ProfileInt 
           where ProfileInt.ProfileId=FTM.Profileid 
           order by ProfileInt.Id desc) 
      )LatestInterventionName 

Und dann natürlich die Spaltennamen wie dies in der SELECT, um etwas zu ändern:

, LatestInterventionStatusId.LatestInterventionStatusId 
, LatestInterventionName.LatestInterventionName 

des Gebens eines Go und lass es mich wissen, wenn es anders ist.

0

Ok, Sie haben mir keine Antwort auf meine Frage gegeben, aber die Unterabfragen sollten geändert werden. Versuchen Sie stattdessen, die beiden Unterabfragen zu verwenden:

/* 
... 
, emp.DateOfBirth as EmployeeDOB 
, addr.PostCode 
, coninfo.Email 
*/ 
, p.StatusId as LatestInterventionStatusId 
, p.name  as LatestInterventionName 

from FTM_Profile FTM 

OUTER APPLY (
    select TOP 1 Intr.name, ProfileInt.StatusId 
    from dbo.PR_Profileintervention ProfileInt 
     LEFT JOIN dbo.FTM_Intervention Intr ON Intr.Id = ProfileInt.InterventionId 
    where ProfileInt.ProfileId = FTM.Profileid 
    order by ProfileInt.Id desc 
) p 
/* 
LEFT JOIN dbo.ProfileManagersView mgrs ON mgrs.ProfileID = FTM.ProfileID 
INNER JOIN dbo.Customer cust on cust.Id= FTM.CustomerId 
INNER JOIN dbo.Employee emp on emp.Id = FTM.EmployeeId 
... 
*/