8
votes

Query lente lors de la connexion au serveur lié

J'ai cette requête

Mettre à jour LinkeddDB ... Set de table Field1 = 'Y' Où Column1 = '1234'

Cela prend 23 secondes pour sélectionner et mettre à jour une ligne

Mais si j'utilise OpenQuery (que je ne veux pas), cela ne prend qu'une demi-seconde.

La raison pour laquelle je ne veux pas utiliser OpenQuery est donc afin que je puisse ajouter des paramètres à ma requête de manière sécurisée et être à l'abri des injections SQL.

Est-ce que quelqu'un sait de quelque raison que ce soit de courir si lentement?


1 commentaires

Des indices du plan d'exécution de la requête? Ou vous pouvez configurer le profileur SQL pour regarder la base de données et voir quelle openquerie fait différemment.


4 Réponses :


2
votes

est la clé primaire de colonne1? Probablement pas. Essayez de sélectionner les enregistrements de la mise à jour à l'aide de la touche primaire (où pk_field = xxx), sinon (parfois?) Tous les enregistrements seront lus pour rechercher PK pour les enregistrements à mettre à jour.


3 commentaires

Je suis à peu près sûr que la colonne1 est la principale clé, mais en regardant le plan d'exécution de SQL Query Analyzer, il montre que la numérisation à distance prend la plus longue, il semble donc qu'il apparaisse à tous les 40 000 enregistrements.


Hmm, si votre PK est (n) Varchar, vous pouvez avoir un problème de rassemblement (je veux dire que SQL n'utilise pas un tel index car il ne sait pas la classée ou de même). Je n'ai aucune expérience avec des champs pk non entiers.


@Jamie, I Deuxième théorie de l'Arvo de la collation étant un problème potentiel



1
votes

Colonne1 a-t-il un champ de varchar? Est-ce pourquoi vous entourez la valeur 1234 avec des guillemets simples? Ou est-ce simplement une faute de frappe dans votre question?


1 commentaires

Si j'exécute la requête dans Query Analyzer sans les guillemets, je reçois une erreur et je crois que la colonne1 est un champ de varchar.



9
votes

Voici une pensée comme une alternative. Créez une procédure stockée sur le serveur distant pour effectuer la mise à jour, puis appelez cette procédure à partir de votre instance locale.

/* On remote server */
create procedure UpdateTable
    @field1 char(1),
    @column1 varchar(50)
as
    update table
        set field1 = @field1
        where column1 = @column1
go

/* On local server */
exec linkeddb...UpdateTable @field1 = 'Y', @column1 = '1234'


6 commentaires

@Joe - est une procédure stockée essentiellement juste une fonction / une méthode pour une base de données?


@orokusaki: Oui, vous pouvez y penser de cette façon.


@Joe Ceci ne fonctionnera que légèrement plus vite, en raison de la suppression de l'analyse et de compiler l'heure. @orokusaki C'est toujours meilleur que votre méthode car elle permet à la base de données de se protéger de l'injection SQL. Vous pouvez également définir des autorisations afin que l'utilisateur ne puisse pas mettre à jour la table directement et ne peut le faire que via le SP.


@Overflow: En réalité, j'attends une amélioration plus significative que la charge de travail pour effectuer la mise à jour est décalée sur le moteur SQL du serveur distant. Dans la version actuelle de l'OP, le moteur SQL local tente de mettre à jour la ressource distante.


@Joe, ce comportement dépend-il de SMDBM ou de pilotes spécifiques? J'ai dirigé les deux versions sur les données sur le réseau avec Wireshark, ont abouti à une requête envoyée au serveur, données renvoyées. Que devrais-je m'attendre à voir si le moteur SQL local exécutait la requête? J'aurais imaginé d'obtenir des données sur le cache local et de l'envoi de données mises à jour en vrac, ou de la récupération et de la mise à jour de la ligne par ligne.


Cela aiderait à atténuer les problèmes de garantie potentiels. De plus, il suffirait de donner des autorisations d'exécutions à l'un SP pour la connexion appropriée au lieu d'autorisations de table directe.



4
votes

Si vous recherchez le pourquoi , voici une possibilité de Blog de Linchi Shea :

créer les meilleurs plans de requête lorsque Vous utilisez une table sur un lien serveur, le processeur de requête doit avoir statistiques de la distribution de données de la serveur lié. Les utilisateurs qui ont limité autorisations sur toutes les colonnes de la la table pourrait ne pas avoir suffisamment Autorisations pour obtenir tout l'utile statistiques et pourrait recevoir des conséquences Plan de requête efficace et expérience mauvaise performance. Si le lien Serveris une instance de SQL Server, à obtenir toutes les statistiques disponibles, le l'utilisateur doit posséder la table ou être membre du rôle de serveur fixe Sysadmin, le rôle de base de données db_ownerfixed, ou le DB_DDLADMIN Rôle de base de données fixe sur le LinkedServer.

(à cause de la poste de Linchi, cette clarification a été ajoutée à la dernière documentation SQL de Booksonline).

En d'autres termes, si le serveur lié est configuré avec un utilisateur comportant des autorisations limitées, alors SQL ne peut pas récupérer des statistiques précises pour la table et choisir une méthode médiocre d'exécution d'une requête, y compris la récupération de toutes les lignes. < / p>

Voici un associé à la question sur la performance de requête liée au serveur. Leur conclusion était la suivante: utilisez OpenQuery pour la meilleure performance.

mise à jour: certains Excellents postes supplémentaires à propos de Performances de serveur liées du blog de Linchi.


0 commentaires