Prestatieprobleem bij het uitvoeren van query's op weergaven op gekoppelde servers

Van toepassing op: SQL Server

Symptomen

Het uitvoeren van een query op weergaven op een gekoppelde server kost meer tijd dan het rechtstreeks uitvoeren van dezelfde query op een basistabel op de gekoppelde server.

Oorzaak

Het uitvoeren van een query voor een weergave en een basistabel resulteert in een ander gedrag vanwege de schatting van de gegevenskardinaliteit, die wordt gebruikt voor het berekenen van het verwachte aantal geretourneerde rijen. Het getal voor het uitvoeren van queryweergaven wordt ingesteld op een constante waarde van 10.000, terwijl het aantal voor het uitvoeren van query's op basistabellen wordt afgeleid van statistische informatie.

Kardinaliteitschatting op een basistabel die wordt opgevraagd door gekoppelde servers

De Microsoft OLE DB-provider (SQLOLEDB) (niet meer onderhouden) of Microsoft® OLE DB-stuurprogramma 18 voor SQL Server® (MSOLEDBSQL) ondersteunen beide distributiestatistieken op basistabellen. SQL Server kan de statistieken en het histogram op gekoppelde servers op dezelfde manier gebruiken als bij elke reguliere query. Als u bijvoorbeeld een gekoppelde server met de naam LS1 maakt die de AdventureWorks2019 database met de Sales.SalesOrderDetail tabel bevat, kunnen de volgende query's gebruikmaken van het statistische histogram:

SELECT * FROM LS1.AdventureWorks2019.Sales.SalesOrderDetail;
SELECT * FROM LS1.AdventureWorks2019.Sales.SalesOrderDetail WHERE SalesOrderID=43659;

In de volgende grafische queryplannen ziet u het geschatte aantal rijen dat wordt geretourneerd voor elke externe query.

Schermopname van de query voor tabel in gekoppelde server.

Kardinaliteitschatting voor weergaven die worden opgevraagd door gekoppelde servers

Gekoppelde serverquery's voor weergaven maken geen gebruik van schatting van kardinaliteit op basis van statistieken. De kardinaliteitschatting voor een weergave is een constante waarde van 10.000. De volgende test illustreert dit:

  1. Maak een weergave met de naam dbo.View1 die verwijst naar de Sales.SalesOrderDetail tabel uit de AdventureWorks2019 database van de gekoppelde server LS1.

    USE AdventureWorks2019;
    GO
    CREATE VIEW [dbo].[view1]
    AS
    SELECT * FROM Sales.SalesOrderDetail;
    
  2. Query's uitvoeren op de weergave op afstand.

    SELECT * FROM LS1.AdventureWorks2019.dbo.view1;
    
  3. De kardinaliteitschatting van de query toont precies 10.000 rijen.

    Schermopname van de query voor weergave op de gekoppelde server.

Kardinaliteitschatting voor een weergave die wordt opgevraagd door gekoppelde servers met WHERE-component

Als u een query uitvoert met de WHERE component voor weergaven op een gekoppelde server, is de kardinaliteitschatting voor weergaven ook een constante waarde. De waarde is echter afhankelijk van het compatibiliteitsniveau van de database.

Notitie

De schattingswaarde voor kardinaliteit wordt niet beïnvloed door het compatibiliteitsniveau van de database waarin de weergave is gedefinieerd.

  • Voor een databasecompatibiliteitsniveau van 120 of hoger (nieuwe versie van kardinaliteitsschatter) is de kardinaliteitsraming 100.
  • Voor een databasecompatibiliteitsniveau van 110 of lager (verouderde kardinaliteitsschatter) is de kardinaliteitschatting 1000.

Zie de volgende query's voor een voorbeeld:

SELECT * FROM LS1.AdventureWorks2019.dbo.view1
WHERE SalesOrderID=43659 
    OPTION (USE HINT ('FORCE_DEFAULT_CARDINALITY_ESTIMATION'));
GO
SELECT * FROM LS1.AdventureWorks2019.dbo.view1 
WHERE SalesOrderID=43659
OPTION (USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION'));

Zie de volgende kardinaliteitschatting van de query's voor een voorbeeld.

Schermopname van de query voor het weergeven van CE op de gekoppelde server.

Oplossing

In de meeste gevallen is er geen actie nodig omdat de meeste toepassingsworkloads niet worden beïnvloed door de kardinaliteitschatting van weergaven wanneer er query's worden uitgevoerd vanaf gekoppelde servers. Als de werkbelasting wordt beïnvloed, gebruikt u een van de volgende methoden:

  • Werk de weergave bij en wijzig deze als een geïndexeerde weergave. De geïndexeerde weergave heeft ten minste één index met bijbehorende statistieken. Zie de volgende query's om een geïndexeerde weergave te maken en er query's op uit te voeren.

    Notitie

    Met deze methode worden werkelijke statistieken weergegeven die de onderliggende gegevens vertegenwoordigen.

    --Set the options to support indexed views.
    SET NUMERIC_ROUNDABORT OFF;
    SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,
       QUOTED_IDENTIFIER, ANSI_NULLS ON;
    GO
    IF OBJECT_ID ('Sales.vOrderDetails1', 'view') IS NOT NULL
       DROP VIEW Sales.vOrderDetails1;
    GO
    --Create view with schemabinding
    CREATE VIEW Sales.vOrderDetails1
       WITH SCHEMABINDING
       AS  
          SELECT SalesOrderID, 
           SalesOrderDetailID, 
           CarrierTrackingNumber, 
           OrderQty, 
           ProductID,
           UnitPrice,
           UnitPriceDiscount,
           LineTotal,
           ModifiedDate
          FROM Sales.SalesOrderDetail
    GO
    --Create an index on the view
    CREATE UNIQUE CLUSTERED INDEX IDX_V1
       ON Sales.vOrderDetails1 (SalesOrderID, ProductID);
    --Select from the materialized view
    SELECT * FROM LS1.adventureworks2019.Sales.vOrderDetails1;
    

    Zie de volgende kardinaliteitschatting van de query voor een voorbeeld.

    Schermopname van de query voor geïndexeerde weergave op de gekoppelde server.

  • Als u een query uitvoert met de WHERE component, kunt u de kardinaliteitschatting verhogen met behulp van de Query Hint OPTION (USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION')). Deze aanpak kan in sommige gevallen helpen, met name bij het samenvoegen met grote tabellen.

    Notitie

    Deze methode is geschikt voor gevallen waarin in de weergave veel rijen worden weergegeven.

  • Voer de query rechtstreeks uit op de basistabellen in plaats van weergaven op de gekoppelde server, indien van toepassing.

Zie ook