Incidences sur les performances de l'utilisation d'OPENQUERY dans une vue

15

Veuillez voir cette question sur stackoverflow:

J'utilise un pilote ODBC EasySoft pour lier une instance SQL Server 2008 R2 Express à Interbase et j'ai des difficultés à obtenir des métadonnées à partir du serveur distant. En regardant sur le net, les principales suggestions mentionnent toutes l'utilisation d'OPENQUERY au lieu de la syntaxe du serveur lié en quatre parties.

EG Mon approche actuelle (problématique) est ...

CREATE VIEW [LIVE].[vwPRDETS]
AS

SELECT *
FROM [LBLIVE]...[PRDETS] WITH (NOLOCK)

Mais sur certaines tables, j'obtiens l'erreur lors de l'appel de la vue ...

Msg 7353, niveau 16, état 1, ligne 1 Le fournisseur OLE DB "MSDASQL" pour le serveur lié "LBLIVE" a fourni des métadonnées incohérentes. Une colonne supplémentaire a été fournie lors de l'exécution et n'a pas été trouvée au moment de la compilation.

De plus, certaines vues que je ne peux même pas créer car j'obtiens ce qui suit ...

Msg 7315, niveau 16, état 1, ligne 1 Le fournisseur OLE DB "MSDASQL" pour le serveur lié "LBLIVE" contient plusieurs tables qui correspondent au nom "" SYSDBA "." AUDIT_LBABKP "".

Bien qu'il n'y ait qu'un seul des tableaux mentionnés.

L'approche alternative de la recherche sur le net semble être plus comme ...

SELECT *
FROM OPENQUERY(<linked sevrer>, 'SELECT <column list> FROM MyTable')

Donc, ma question est, si j'utilise OPENQUERY dans ma définition de vue, SQL Server pourra-t-il optimiser le SQL résultant envoyé à Interbase? Ou n'y a-t-il vraiment pas beaucoup de différence entre les deux approches?

C'est un sujet croisé et j'adorerais le POV d'un dba.

Rich Andrews
la source

Réponses:

20

Sommaire

Laissez le serveur lié faire autant que possible.
Il est impossible pour SQL Server d'optimiser une requête sur un serveur lié, même un autre SQL Server

Longue

Le facteur clé est l' endroit où la requête s'exécute.

Dans ce cas, il s'agit d'un SELECT trivial, donc toutes les lignes d'une table seront envoyées sur le fil. Ça n'a pas d'importance.

Lorsque vous ajoutez des JOIN et des WHERE, cela peut être important. Vous souhaitez que SQL Server autorise le serveur lié à effectuer autant de filtrage que possible pour réduire la taille des données provenant du réseau.

Par exemple, le 2ème cas ici devrait être plus efficace.

SELECT *
FROM OPENQUERY(<linked server>, 
            'SELECT <column list> FROM MyTable') T1
     JOIN
     SomeLocalTable T2 ON ...
WHERE T1.foo = 'bar'

SELECT *
FROM OPENQUERY(<linked server>, 
           'SELECT <column list> FROM MyTable WHERE foo = ''bar''')
     JOIN
     SomeLocalTable T2 ON ...

Une limitation de OPENQUERY est que vous ne pouvez pas paramétrer: vous avez donc besoin de SQL dynamique pour ajouter des clauses WHERE, etc.

Les performances des serveurs liés peuvent être affectées par sp_serveroption. Le cadre collation compatibledit tout

Si cette option est définie sur true, SQL Server suppose que tous les caractères du serveur lié sont compatibles avec le serveur local, en ce qui concerne le jeu de caractères et la séquence de classement (ou l'ordre de tri). Cela permet à SQL Server d'envoyer des comparaisons sur des colonnes de caractères au fournisseur. Si cette option n'est pas définie, SQL Server évalue toujours les comparaisons sur les colonnes de caractères localement.

Autrement dit, essayez de ne pas laisser SQL Server traiter les données localement.

Remarque: Sur mon foo = 'bar'2ème exemple ci-dessus, le filtre est envoyé au serveur lié car il s'agit simplement d'une constante de chaîne vers SQL Server. La vraie clause WHERE du premier exemple peut ou non être envoyée à distance.

Enfin, j'ai également constaté que le transfert des données dans une table temporaire et leur jonction sur des tables locales est souvent mieux que de se joindre directement à OPENQUERY.

gbn
la source
+1 Pourquoi ma comparaison de clause where simple avec un littéral de chaîne n'était-elle pas exécutée sur le serveur distant? La réponse était "compatible avec le classement". Merci.
mwardm