Laquelle est la plus efficace: sélection du serveur lié ou insertion dans le serveur lié?


32

Supposons que je dois exporter des données d'un serveur à un autre (via des serveurs liés). Quelle déclaration sera plus efficace?

Exécution sur le serveur source:

INSERT INTO [DestinationLinkedServer].[DestinationDB].[dbo].[Table]
SELECT a, b, c, ... FROM [dbo].Udf_GetExportData()

Ou exécutant sur le serveur cible:

INSERT INTO [dbo].[Table]
SELECT a, b, c, ...
FROM OPENQUERY([OriginLinkedServer],
    'SELECT a, b, c, ... FROM [OriginDB].[dbo].Udf_GetExportData()')

Lequel sera le plus rapide et consommera le moins de ressources au total (serveur source et serveur cible)? Les deux serveurs sont SQL Server 2005.

Réponses:


29

Supposons que je doive exporter des données d’un serveur à un autre.

Le mieux est d'utiliser

  • SI vous voulez que toutes les données utilisent Backup / Restore; BCP OUT et BCP IN ou SSIS
  • SI vous voulez un sous-ensemble de données (certaines tables uniquement), utilisez SSIS ou BCP OUT & BCP IN

Pour déplacer les données, en fonction de la quantité / taille des données et de la bande passante n / w, le serveur lié tue les performances.

Exécution sur le serveur source Ou exécution sur le serveur cible - Lequel sera le plus rapide et consommera le moins de ressources au total (serveurs source et cible)?

- Exécution sur le serveur source:

INSERT INTO [DestinationLinkedServer].[DestinationDB].[dbo].[Table]
SELECT a, b, c, ... FROM [dbo].Udf_GetExportData()

Cette opération s'appelle PUSHING Data car vous exécutez la requête sur le serveur source et transférez les données sur le serveur de destination. Ce sera une opération coûteuse.

--- en cours d'exécution sur le serveur cible

INSERT INTO [dbo].[Table]
SELECT a, b, c, ...
FROM OPENQUERY([OriginLinkedServer],
    'SELECT a, b, c, ... FROM [OriginDB].[dbo].Udf_GetExportData()')

Cette opération s'appelle PULLING Data car vous exécutez la requête sur le serveur de destination et extrayez les données du serveur source. Ce sera beaucoup plus rapide et moins gourmand en ressources que l'ancien (en fonction de la quantité de données extraites).

Dans le cas de la méthode pull, l'utilisation de SQL Profiler vous permet de voir qu'une seule instruction SQL est exécutée sur le serveur lié (serveur source) et que l'ensemble de résultats est extrait du serveur source vers le serveur de destination, ce qui représente un gain de performances considérable par rapport à PUSH. méthode.

Un autre point à noter est:

Entre le serveur lié (convention de dénomination en 4 parties utilisée nom_serveur.databasename.schema.tablename ou Requêtes distribuées) et OPENQUERY, généralement OPENQUERY sera rapide. Pourquoi ?

Pour le serveur lié - l’optimiseur de requêtes crée un plan d’exécution en consultant la nomenclature des requêtes et en le découpant en requêtes distantes et locales. Les requêtes locales sont exécutées localement et les données des requêtes distantes sont collectées à partir des serveurs distants, nettoyées localement, combinées et présentées à l'utilisateur final sous la forme d'un jeu d'enregistrements unique.

For OPENQUERY - Exécute la requête directe spécifiée sur le serveur lié spécifié. SQL Server envoie des requêtes directes sous forme de chaînes de requête non interprétées à une source de données OLE DB. Par conséquent, SQL n'appliquera aucun type de logique à la requête et n'essayera pas d'estimer ce que ferait cette requête, il transmettra simplement la requête spécifiée telle quelle au serveur lié cible. Les requêtes ouvertes sont utiles lorsque vous ne faites pas référence à plusieurs serveurs dans une requête. C'est généralement rapide car SQL ne le divise pas en plusieurs opérations et n'effectue aucune action locale sur la sortie reçue.

Excellentes références de lecture:


8

Comment mesurez-vous l'efficacité? Lequel sera le plus rapide? Lequel consommera le moins de ressources sur la cible? sur la source? Combien de lignes et quel type de types de données sont les colonnes dans ces lignes? Êtes-vous sûr de pouvoir exécuter un fichier TVF via un serveur lié (la cible est-elle SQL 2008 ou ultérieure?) ? Comment assurez-vous une migration 1: 1 de ces données si vous extrayez d'un fichier TVF?

Avec ces questions sur le chemin ...

Mise à jour 1

On dirait que vous recherchez ETL (Extract-Transform-Load). Je recommande SSIS (SQL Server Integration Services) avec lequel vous pouvez extraire les données de la source, appliquer les transformations dont vous avez besoin, puis les charger dans votre cible. Cela ressemble à un package assez simple (en fonction des transformations).


Selon la sagesse conventionnelle, l'approche du serveur lié ira au lien, extraira les données au serveur local, puis appliquera toute logique (filtres, jointures, etc.) au serveur local. Il y a une surcharge à récupérer les données sur le serveur lié, mais la majorité du traitement sera traitée localement.

La méthode OPENQUERY mettra le traitement sur le serveur distant et les "résultats filtrés" seront reçus par le serveur local.

Il semble que même si vous pouviez exécuter un fichier TVF via un serveur lié, vous auriez le pire des deux mondes, le traitement à distance et le traitement local (en supposant que vous disposiez d'une logique supplémentaire à appliquer sur le plateau).

En fonction de la manière dont vous décidez d'aller de l'avant, j'aimerais également examiner OPENQUERYun moyen d'importer / exporter en masse les données.

Ayant dit tout cela ...

Si la source et la cible sur SQL Server (et la cible n'est pas une version inférieure), pourquoi ne pas effectuer une sauvegarde et une restauration des données? Ce serait une véritable migration de données. Voici du code pour vous.

BACKUP DATABASE <DatabaseName, sysname, DatabaseName>
TO DISK=N'<backup_location, varchar, BackupLocation>.bak'
WITH INIT, FORMAT, COMPRESSION, COPY_ONLY

RESTORE DATABASE <NewDatabaseName, sysname, NewDatabaseName>
FROM DISK = N'<backup_location, varchar, BackupLocation>\
    <DatabaseName, sysname, DatabaseName>.bak'
WITH 
    MOVE '<DataFileName, sysname, DataFileName>' TO '<DataMDFPath, nvarchar(600), DataMDFPath>',
    MOVE '<LogFilePath, sysname, LogFilePath>' TO '<LogLDFPath, nvarchar(600), LogLDFPath>',
    REPLACE;

Vous pouvez vous référer à cette réponse pour savoir comment utiliser les modèles dans SSMS.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.