Eu tenho dois servidores de banco de dados, conectados via servidores vinculados. Ambos são bancos de dados do SQL Server 2008R2 e a conexão do servidor vinculado é feita por um link "SQL Server" regular, usando o contexto de segurança do logon atual. Os servidores vinculados estão no mesmo centro de dados, portanto, a conexão não deve ser um problema.
Eu uso a seguinte consulta para verificar quais valores da coluna identifier
estão disponíveis remotamente, mas não localmente.
SELECT
identifier
FROM LinkedServer.RemoteDb.schema.[TableName]
EXCEPT
SELECT DISTINCT
identifier
FROM LocalDb.schema.[TableName]
Nas duas tabelas há índices não agrupados na coluna identifier
. Localmente, existem cerca de 2,6 milhões de linhas, remotamente, apenas 54. No entanto, ao analisar o plano de consulta, 70% do tempo de execução é dedicado à "execução de consulta remota". Além disso, ao estudar o plano de consulta completo, o número de linhas locais estimadas é em 1
vez de 2695380
(que é o número de linhas estimadas ao selecionar apenas a consulta seguinte EXCEPT
).
Ao executar esta consulta, leva muito tempo.
Isso me faz pensar: por que isso? A estimativa está "apenas" muito distante, ou as consultas remotas nos servidores vinculados são realmente tão caras?
Respostas:
O plano que você tem no momento parece o melhor para mim.
Não concordo com a afirmação nas outras respostas de que ele está enviando as linhas de 2.6 milhões para o servidor remoto.
O plano parece-me que, para cada uma das 54 linhas retornadas da consulta remota, ele esteja executando uma pesquisa de índice em sua tabela local para determinar se é ou não compatível. Este é praticamente o plano ideal.
Substituir por uma junção de hash ou junção de mesclagem seria contraproducente, dado o tamanho da tabela e a adição de uma
#temp
tabela intermediária apenas adiciona uma etapa adicional que parece não oferecer nenhuma vantagem.fonte
Conectar-se a um recurso remoto é caro. Período.
Uma das operações mais caras em qualquer ambiente de programação é a E / S de rede (embora a E / S de disco tenda a diminuí-la).
Isso se estende aos servidores vinculados remotos. O servidor que está chamando o servidor vinculado remoto precisa primeiro estabelecer uma conexão; depois, uma consulta precisa ser executada no servidor remoto, os resultados retornados e a conexão fechada. Tudo isso leva tempo na rede.
Você também deve estruturar sua consulta de forma a transferir os dados mínimos pela conexão. Não espere que o banco de dados otimize para você.
Se eu escrevesse essa consulta, selecionaria os dados remotos em uma variável de tabela (ou em uma tabela temporária) e usaria isso em conjunto com a tabela local. Isso garante que apenas os dados que precisam ser transferidos o sejam.
A consulta que você está executando pode facilmente enviar 2,6 milhões de linhas para o servidor remoto para processar a
EXCEPT
cláusula.fonte
Não sou especialista, mas se você estiver usando Union, Except ou Intersect, não precisará usar "Distinct". Dependendo dos valores do LocalDb.schema. [TableName], o desempenho da consulta pode ser aprimorado.
fonte
Oded está certo, o problema de desempenho é causado pelo envio das linhas de 2.6 milhões para o servidor remoto.
Para corrigir esse problema, você pode forçar o envio de dados remotos (54 linhas) usando uma tabela temporária ou na memória.
Usando uma tabela temporária
fonte
Eu acho que é melhor replicar a tabela remota para o servidor do qual você está consultando e depois executar todo o seu SQL localmente.
fonte