Les performances sont lentes lorsque vous exécutez une requête dans SQL Server 2005 qui met à jour une table sur un serveur lié et joint ensuite ce tableau à un tableau sur le serveur local

Symptômes

Considérez le scénario suivant :
  • Vous avez une requête qui met à jour une table sur un serveur lié et joint ensuite ce tableau à un tableau sur le serveur local.
  • Le serveur local exécute Microsoft SQL Server 2005.
  • Sur le serveur local, vous exécutez la requête dans SQL Server 2005.
Dans ce scénario, les performances sont lentes comparées avec les performances de la même requête dans Microsoft SQL Server 2000. Par exemple, lorsque vous exécutez la requête dans SQL Server 2000, la requête prend moins d’une seconde à la fin. Toutefois, lorsque vous exécutez la requête dans SQL Server 2005, la requête prend environ 24 secondes pour terminer.

Cause

La requête effectue une opération d’analyse à distance sur la table sur le serveur lié. Lorsque vous exécutez la requête dans SQL Server 2005, l’opération Remote Scan extrait toutes les lignes de la table. Si la table contient un nombre de lignes, l’opération d’analyse à distance prend beaucoup de temps pour terminer.

Toutefois, lorsque vous exécutez la requête dans SQL Server 2000, l’opération de requête à distance envoie la requête à exécuter sur le serveur lié. Par conséquent, même si le tableau contient plusieurs lignes, analyse à distance l'terminée en peu de temps.

Solution de contournement

Pour contourner ce problème, ajoutez une contrainte UNIQUE ou une contrainte de clé primaire de la table sur le serveur local. Ajouter la contrainte à la colonne que vous utilisez pour l’opération de jointure.

Par exemple, vous mettez à jour l’instruction DECLARE mentionné à l’étape 4 de la section « Informations complémentaires » à la suivante :
DECLARE @t2 table (c1 int primary key, c2 int)

État

Microsoft a confirmé l'existence de ce problème dans les produits Microsoft répertoriés dans la section « S'applique à ».

Plus d'informations

Étapes pour reproduire le problème


Remarque Les étapes suivantes supposent que vous disposez de deux serveurs qui exécutent SQL Server 2005. Un nom d’instance est ServerA\SQL2005. L’autre nom de l’instance est ServerB\SQL2005.
  1. Sur l’instance de serveur de SQL Server 2005, exécutez les instructions suivantes pour créer une base de données dans SQL Server Management Studio :
    USE MASTERGO
    IF EXISTS (SELECT * FROM sysdatabases where name = 'LinktestTarget')
    DROP DATABASE LinktestTarget
    GO
    CREATE DATABASE LinktestTarget
    GO

    ALTER DATABASE LinktestTarget MODIFY FILE
    (NAME = 'LinktestTarget', SIZE = 200MB)
    GO
    ALTER DATABASE LinktestTarget MODIFY FILE
    (NAME = 'LinktestTarget_log', SIZE = 100MB)
    GO
  2. Sur l’instance de serveur b de SQL Server 2005, exécutez les instructions suivantes pour créer un serveur lié dans Management Studio :
    DECLARE @serverName nvarchar(50)SET @serverName = @@serverName

    IF EXISTS (SELECT * FROM master..sysservers WHERE srvname = 'LS')
    EXEC master.dbo.sp_dropserver @server=N'LS', @droplogins='droplogins'

    EXEC sp_addlinkedserver
    @server = N'LS',
    @srvproduct = N'SQLDB',
    @provider = N'SQLOLEDB',
    @datasrc = N'ServerA\SQL2005',
    @catalog = N'LinktestTarget'

    EXEC sp_serveroption N'LS', N'data access', N'true'
    EXEC sp_serveroption N'LS', N'rpc out', N'true'
    EXEC sp_serveroption N'LS', N'rpc', N'true'
    EXEC sp_serveroption N'LS', N'use remote collation', N'true'
    EXEC sp_addlinkedsrvlogin
    @rmtsrvname = N'LS',
    @useself = N'true',
    @locallogin = N'sa'
  3. Sur l’instance de serveur de SQL Server 2005, exécutez l’instruction suivante pour créer une table et puis remplir le tableau avec 50 000 lignes de données :
    USE LinktestTargetGO
    CREATE TABLE [T1] (
    [c1] [int] NOT NULL,
    [c2] [int] NOT NULL,
    [c3] char (4000) NOT NULL,
    CONSTRAINT [PK_t1] PRIMARY KEY CLUSTERED ([c1])
    WITH FILLFACTOR = 80 ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    SET NOCOUNT ON
    GO
    DECLARE @counter int
    SET @counter = 1

    WHILE @counter < 50000
    BEGIN
    INSERT INTO T1 (c1, c2, c3) VALUES (@counter, @counter,'')
    SET @counter = @counter + 1
    END
    GO
    UPDATE STATISTICS T1 (PK_t1) WITH FULLSCAN
  4. Sur l’instance de serveur b de SQL Server 2005, exécutez les instructions suivantes. Notez que les performances sont lentes.
    DECLARE @t2 table (c1 int, c2 int)INSERT INTO @t2 (c1, c2) VALUES (399990, 399990)

    UPDATE A
    SET A.c2 = B.c2
    FROM LS.LinktestTarget.dbo.T1 AS A
    JOIN @t2 as B on B.c1 = A.c1
Propriétés

ID d'article : 942982 - Dernière mise à jour : 17 janv. 2017 - Révision : 1

Commentaires