Qual é o mais eficiente: selecione no servidor vinculado ou insira no servidor vinculado?

32

Suponha que eu precise exportar dados de um servidor para outro (por meio de servidores vinculados). Qual afirmação será mais eficiente?

Executando no servidor de origem:

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

Ou executando no servidor de destino:

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

Qual deles será mais rápido e consumirá menos recursos no total (servidor de origem e de destino)? Ambos os servidores são SQL Server 2005.

Guillermo Gutiérrez
fonte

Respostas:

29

Suponha que eu tenha que exportar dados de um servidor para outro.

O melhor é usar

  • Se você deseja que todos os dados usem Backup / Restauração; BCP OUT e BCP IN ou SSIS
  • SE você deseja um subconjunto de dados (apenas algumas tabelas), use SSIS ou BCP OUT & BCP IN

Para mover dados, dependendo da quantidade / tamanho dos dados e da largura de banda n / w, o servidor vinculado reduzirá o desempenho.

Executando no servidor de origem Ou executando no servidor de destino - Qual deles será mais rápido e consumirá menos recursos no total (servidor de origem e de destino)?

- Executando no servidor de origem:

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

Isso se chama PUSHING Data, enquanto você executa a consulta no servidor de origem e envia os dados para o servidor de destino. Isso será uma operação cara.

--- executando no servidor de destino

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

Isso se chama PULLING Data, à medida que você executa a consulta no servidor de destino e extrai dados do servidor de origem. Isso será muito mais rápido e consumirá menos recursos em comparação com o anterior (dependendo da quantidade de dados que está sendo extraída).

No caso do método pull, usando o SQL Profiler, você verá que uma única instrução SQL é executada no servidor vinculado (servidor de origem) e o conjunto de resultados é transferido do servidor de origem para o servidor de destino, o que representa um enorme ganho de desempenho em relação ao PUSH método.

Outro ponto a ser observado é:

Entre o servidor vinculado (convenção de nomenclatura de 4 partes usada servername.databasename.schema.tablename aka Distributed Queries) e OPENQUERY, geralmente OPENQUERY será rápido. Por quê ?

Para servidor vinculado - o otimizador de consultas cria um plano de execução observando a nomenclatura da consulta e divide-a em consultas remotas e locais. As consultas locais são executadas localmente e os dados para consultas remotas são coletados dos servidores remotos, limpos localmente, combinados e apresentados ao usuário final como um único conjunto de registros.

Para OPENQUERY - Executa a consulta de passagem especificada no servidor vinculado especificado. O SQL Server envia consultas de passagem como seqüências de caracteres não interpretadas para uma fonte de dados OLE DB. Portanto, o SQL não aplicará nenhum tipo de lógica à consulta e não tentará estimar o que essa consulta faria; simplesmente passaria a consulta especificada como está para o servidor vinculado ao destino. As consultas abertas são úteis quando você não está referenciando vários servidores em uma consulta. Geralmente é rápido, pois o SQL não o divide em várias operações e não executa nenhuma ação local na saída recebida.

Excelentes referências de leitura:

Kin Shah
fonte
8

Como você está medindo a eficiência? Qual será mais rápido? Qual deles consumirá menos recursos no destino? na fonte? Quantas linhas e que tipo de tipos de dados são as colunas nessas linhas? Tem certeza de que pode executar um TVF por meio de um servidor vinculado (o SQL 2008 de destino ou posterior?) ? Como você está assegurando uma migração 1: 1 desses dados, se estiver usando um TVF?

Com essas perguntas fora do caminho ...

Atualização 1

Parece que você está procurando ETL (Extract-Transform-Load). Eu recomendo o SSIS (SQL Server Integration Services) com o qual você pode extrair os dados da origem, aplicar as transformações necessárias e carregá-las no seu destino. Parece que seria um pacote bastante simples (dependendo das transformações).


O senso comum afirma que a abordagem do servidor vinculado será direcionada ao link, puxará os dados para o servidor local e aplicará qualquer lógica (filtros, junções etc.) no servidor local. Há alguma sobrecarga para buscar os dados no servidor vinculado, mas a maioria do processamento será tratada localmente.

O método OPENQUERY colocará o processamento no servidor remoto e os "resultados filtrados" serão recebidos pelo servidor local.

Parece que, mesmo se você pudesse executar um TVF através de um servidor vinculado, estaria recebendo o pior dos dois mundos, processando remotamente e localmente (supondo que você tivesse lógica adicional para aplicar no aparelho).

Dependendo de como você decide avançar, eu também consideraria OPENQUERYum meio de importar / exportar dados em massa.

Tendo dito tudo isso ...

Se a origem e o destino no SQL Server (e o destino não são uma versão inferior), por que não fazer um backup e restauração dos dados? Isso seria uma verdadeira migração de dados. Aqui está um código para você.

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;

Você pode consultar esta resposta sobre como usar modelos no SSMS.

swasheck
fonte