requête sql server lenteur de java
J'ai un programme java qui s'exécute en un tas de requêtes sur une base de données sql server. La première de ces requêtes à l'encontre d'une vue renvoie sur 750k enregistrements. Je peux exécuter la requête via sql server management studio, et j'obtiens des résultats dans environ 30 secondes. cependant, j'ai débuté le programme à exécuter la nuit dernière. quand j'ai vérifié ce matin, cette requête n'avait pas encore retourné les résultats pour le programme java, à 15 heures plus tard.
J'ai accès à la base de données pour faire à peu près tout ce que je veux, mais je ne suis vraiment pas sûr de savoir comment commencer le débogage. Que doit-on faire pour savoir ce qui est à l'origine de ce genre de situation? Je ne suis pas administrateur de base de données, et je ne suis pas intimement familier avec le sql server configuration de l'outil, de sorte que le plus de détails vous pouvez me donner sur la façon de faire ce que vous pourriez suggérer serait appréciée.
heres le code
stmt = connection.createStatement();
clientFeedRS = stmt.executeQuery(StringBuffer.toString());
EDIT1:
Bien ça fait un moment, et il s'est détourné, mais ce problème est de retour. J'ai regardé dans la mise à niveau du pilote jdbc v 1.2 à 2.0, mais nous sommes coincés sur jdk 1.4, et v 2.0 exigent jdk 1.5, donc c'est un non-starter. Maintenant, je suis à la recherche de mon propriétés de chaîne de connexion. Je vois 2 qui pourrait être utile.
SelectMethod=cursor|direct
responseBuffering=adaptive|full
Actuellement, avec le problème de latence, je suis en cours d'exécution avec le curseur, comme le selectMethod, et avec la valeur par défaut pour responseBuffering qui est plein. Est la modification de ces propriétés susceptibles de les aider? si oui, quel en serait l'idéal? Je suis en train de penser, basé sur ce que je peux trouver en ligne, qui à l'aide d'une sélection directe de la méthode et de la réponse adaptative de mise en mémoire tampon qui pourrait résoudre mon problème. toutes les pensées?
EDIT2:
Bien j'ai fini de changer à la fois de ces de la chaîne de connexion params, à l'aide de la valeur par défaut sélectionner la méthode(direct) et en spécifiant le responseBuffering adaptatif. Il finit par ce qui marche le mieux pour moi et soulage les problèmes de latence, j'ai été voir. merci pour toute l'aide.
Quel est le programme Java? Un extrait de code de la façon dont vous êtes accédant à la DB est certainement nécessaire. Aussi, est-SQL Server Studio de limiter les résultats (pour, par exemple, les 1000 premières lignes) qui pourrait biaiser les résultats?
si elle était de limiter les résultats à 1k lignes, comment puis-je être sûr qu'il ne l'est pas?
Sont SSMS et votre application Java s'exécutant dans le même lieu? Si SSM est exécuté localement sur le Serveur SQL, et votre application Java n'est pas le cas, ce n'est pas exactement un niveau de comparaison.
oui, l'exécution de la requête via SSMS, au même endroit, je suis de l'exécution de l'application java.
OriginalL'auteur shsteimer | 2009-06-07
Vous devez vous connecter pour publier un commentaire.
Assurez-vous que votre pilote JDBC est configuré pour utiliser une connexion directe et pas un cusror en fonction de la connexion. Vous pouvez poster votre connexion JDBC URL si vous n'êtes pas sûr.
Assurez-vous que vous utilisez une seule, en lecture seule (cela est la valeur par défaut si vous n'êtes pas de réglage).
Et assurez-vous que vous utilisez la mise à jour des pilotes JDBC.
Si tout cela ne fonctionne pas, alors vous devriez regarder dans le générateur de profils sql et essayer de capturer la requête sql que le pilote jdbc exécute l'instruction, et d'exécuter cette instruction dans le management studio et de voir si il y a une différence.
Aussi, puisque vous êtes en tirant une telle quantité de données, vous devriez essayer pour être sûr de ne pas avoir la mémoire/la collecte des ordures ralentissements sur la JVM (même si dans ce cas ce n'est pas vraiment expliquer la différence de temps).
En fonction de Microsoft docs, Directe est plus rapide. Vous devez uniquement utiliser les curseurs si vous avez besoin de la ligne par ligne d'accès (ou JDBC, si vous avez besoin des transactions distribuées sur plusieurs base de données, vous n'avez pas le choix.
OriginalL'auteur Yishai
J'ai eu le même problème, avec un très simple requête (SELECT . PARTIR de . OÙ = .) prendre jusqu'à 10 secondes pour retourner une seule ligne lorsque vous utilisez une connexion jdbc Java, tout en prenant seulement de 0,01 s dans sqlshell. Le problème est le même si j'ai été en utilisant le officiel MS SQL pilote ou le JTDS pilote.
La solution était de l'installation de cette propriété dans l'url jdbc :
sendStringParametersAsUnicode=false
Exemple complet si vous utilisez MS SQL pilote officiel: jdbc:sqlserver://yourserver;instanceName=yourInstance;databaseName=yourDBName;sendStringParametersAsUnicode=false;
Instructions si vous utilisez différents pilotes jdbc et de plus amples infos sur le problème ici : http://emransharif.blogspot.fr/2011/07/performance-issues-with-jdbc-drivers.html
Dans mon cas, j'ai eu 30M+ enregistrements dans la table j'étais à la recherche de. La durée pour compléter la demande est passé de plus de 10 secondes, à environ 0,01 s après l'application de la propriété.
Espère que cela va aider quelqu'un !
Merci merci merci! Cela m'a sauvé la vie: il avait vraiment un gros problème de performance avec une très simple question: ce paramètre modifié les temps de requête via JDBC de quelques secondes à quelques millisecondes!
nice. cela a provoqué la requête à exécuter en moins de 5 secondes ,au lieu de 80 sec.
OriginalL'auteur Khopa
Il semble que cela peut ne pas avoir appliqué à votre situation particulière, mais j'ai voulu donner une autre explication possible pour une personne à la recherche de ce problème.
J'ai juste eu un problème similaire où une requête exécutée directement dans SQL Server a fallu 1 minute alors que la même requête a pris 5 minutes grâce à un java préparé statemnent. Je le suivi qu'il est le fait qu'il a été fait comme une déclaration préparée.
Lorsque vous exécutez une requête directement dans SQL Server, vous offrir une requête non paramétrée, dont il connaît tous les critères de recherche d'optimisation du temps. Dans mon cas, mes critères de recherche inclus une plage de dates, et SQL server a été en mesure de regarder, de décider "de cette date, la gamme est énorme, il ne faut pas utiliser la date index", puis il a choisi quelque chose de beaucoup mieux.
Lorsque j'exécute la même requête par le biais d'un java déclaration préparée à l'avance, au moment de SQL Server est l'optimisation de la requête, vous n'avez pas encore fourni une des valeurs de paramètres, de sorte qu'il a à faire une estimation de l'index à utiliser. Dans le cas de ma plage de dates, si il optimise pour une petite gamme et je lui donne une large gamme, il va effectuer plus lentement qu'il le pouvait. Même si il optimise pour une large gamme et je lui donne un petit, c'est encore d'aller à effectuer plus lentement qu'il le pouvait.
À démontrer, c'était bien le problème, comme une expérience, j'ai essayé de donner des indications quant à ce qu'à l'optimisation de l'utilisation de SQL Server "OPTIMISER" option. Quand je disais à utiliser une petite plage de dates, mon java requête (qui avait effectivement une large plage de dates) ont deux fois plus longtemps qu'avant (10 minutes au lieu de 5 minutes avant, et par opposition à 1 minute dans SQL Server). Quand j'ai dit à mes dates exactes pour l'optimiser, le temps d'exécution est identique entre le java instruction préparée.
Si ma solution était de coder en dur les dates exactes dans la requête. Cela a fonctionné pour moi parce que c'était juste une seule déclaration. La PreparedStatement n'était pas destiné à être réutilisé, mais simplement de paramétrer les valeurs pour éviter d'injection SQL. Depuis ces dates, ont été en provenance de java.sql.L'objet Date, je n'ai pas à vous soucier de mes valeurs à la date d'contenant de l'injection de code.
Cependant, pour une déclaration qui N'a besoin d'être réutilisé, le codage en dur les dates ne fonctionnerait pas. Peut-être une meilleure option serait de créer plusieurs déclarations préparées optimisé pour différentes plages de dates (l'un pour une journée, pour une semaine, pour un mois, pour un an, et un pour une décennie...ou peut-être vous avez seulement besoin de 2 ou 3 options...je ne sais pas) et ensuite, pour chaque requête, d'exécuter une instruction préparée dont l'intervalle de temps correspond le mieux à la plage dans le réel de la requête.
Bien sûr, cela ne fonctionne bien que si votre date de plages sont uniformément distribués. Si 80% de vos dossiers étaient en cours de la dernière année, et 20% répartis sur les 10 années précédentes, de faire les "multiples requêtes sur la base de la taille de portée" chose pourrait ne pas être le meilleur. Vous devez optimiser votre des requêtes basées sur des gammes spécifiques ou quelque chose. Vous aurez besoin de comprendre à travers l'essai une erreur.
Merci pour cette idée! J'ai eu quelques SQL que j'étais en train de connecter un peu plus de 300 valeurs, et je voyais des temps d'exécution, dans mon programme de plus de 100 000 ms. Mais quand j'ai pris la même SQL et il a couru dans MSSQL Studio semblait qu'il semblait courir instantanément. Je n'avais aucune idée de la raison autre que quelque chose de bizarre se passe dans le pilote JDBC. J'ai vu ce post, donc j'ai changé la logique de ne pas utiliser toutes ces variables, et maintenant les requêtes sont en cours d'exécution 500 fois plus rapide!! À des vitesses équivalentes à ce que je voyais à l'extérieur de mon programme. Incroyable.
OriginalL'auteur ldkronos
Si la requête est paramétrées, il peut être un paramètre manquant ou un paramètre qui est défini avec la fonction incorrecte, par exemple setLong de chaîne de caractères, etc.
Essayez d'exécuter votre requête avec tous les paramètres codés en dur dans le corps de la requête, sans
?
pour voir si c'est un problème.OriginalL'auteur Leon Fleysher
Je sais que c'est une vieille question, mais puisque c'est l'un des premiers résultats lors d'une recherche de ce problème, j'ai pensé que je devrais poster ce qui a fonctionné pour moi. J'ai eu une requête qui a pris moins de 10 secondes lorsque j'ai utilisé du pilote JDBC SQL Server, mais plus de 4 minutes lors de l'utilisation de jTDS. J'ai essayé toutes les suggestions mentionnées ici et aucun ne fait aucune différence. La seule chose qui a fonctionné, c'est d'ajouter ce point à l'URL ";prepareSQL=1"
Voir Ici pour plus d'
OriginalL'auteur Sol
Tirant vers l'arrière que la quantité de données qui va nécessiter beaucoup de temps. Vous devriez probablement trouver un moyen de ne pas exiger que beaucoup de données dans votre application à tout moment donné. Page de données ou d'utilisation chargement différé par exemple. Sans plus de détails sur ce que vous essayez d'accomplir, c'est difficile à dire.
Comment est votre mémoire à faire sur la boîte?
OriginalL'auteur JP Alioto
Le fait qu'il est rapide lorsqu'il est exécuté à partir de management studio pourrait être dû à une mauvaise mise en cache de plan de requête et de la date index (par exemple, en raison d'un grand importation ou suppressions). Est-ce le retour de tous les 750K rapidement des enregistrements dans SSMS?
Essayez de reconstruire votre index (ou, si cela prendrait trop de temps, de mettre à jour vos statistiques); et peut-être vider le cache de procédure (faites attention si c'est un système de production...):
DBCC FREEPROCCACHE
OriginalL'auteur Mitch Wheat
Pour démarrer le débogage cela, il serait bon de déterminer si le problème est dans la base de données ou dans l'application. Avez-vous essayé de changer la requête telle qu'elle retourne un beaucoup plus petit résultat? Si ce n'est pas de retour, je propose de cibler la façon dont vous accédez à la DB à partir de Java.
OriginalL'auteur akf
Essayez d'ajuster la taille de l'extraction de la Déclaration et essayer selectMethod de curseur
http://technet.microsoft.com/en-us/library/aa342344(SQL.90).aspx
Nous avons eu des problèmes avec de grands ensembles de résultats de l'utilisation de mysql et de faire le nécessaire pour diffuser le jeu de résultats, comme expliqué dans le lien suivant.
http://helpdesk.objects.com.au/java/avoiding-outofmemoryerror-with-mysql-jdbc-driver
OriginalL'auteur objects
Devis à partir de la MS Adaptative tampon lignes directrices:
Et
Voir plus: http://technet.microsoft.com/en-us/library/bb879937.aspx
OriginalL'auteur eugenevd
Parfois, il pourrait être dû à la manière dont les paramètres sont opposables à l'objet de requête.
J'ai trouvé le code suivant est très lent lors de l'exécution du programme java.
Une fois que j'ai enlever le "supprimé" paramètre et directement ajouter que "SUPPRIMÉ" de la chaîne de la requête, il est devenu super rapide. Elle peut être due à SQL server est en attendant d'avoir tous les paramètres liés à décider de l'optimisation du plan.
OriginalL'auteur Shehan Simen
Je sais que c'est une très vieille question, mais puisque c'est l'un des premiers résultats lors d'une recherche pour cette question j'ai pensé que je devrais poster ce qui a fonctionné pour moi.
J'ai eu une requête qui a pris environ 3 secondes quand j'avais l'habitude de SQL Server Management Studio (SSMS), mais a pris 3,5 minutes lors de l'exécution à l'aide de jTDS pilote JDBC via le
executeQuery
méthode.Aucun de la proposition mentionnée ci-dessus a fonctionné pour moi, principalement parce que j'étais juste en utilisant la Déclaration et non d'une Instruction Préparée. La seule chose qui a fonctionné pour moi a été de préciser le nom de la première ou de la base de données par défaut dans la chaîne de connexion, à laquelle l'utilisateur qui se connecte a au moins le db_datareader appartenance au rôle de base de données. N'ayant que la public rôle est pas suffisant.
Voici l'exemple de chaîne de connexion:
Veuillez vous assurer que vous avez de la fin de la
/DefaultDbName
spécifié dans la chaîne de connexion. IciDefaultDbName
est le nom de la base de données à laquelle l'IDENTIFIANT de l'utilisateur spécifié pour la fabrication de la connexion JDBC a au moins ledb_datareader
rôle de base de données. Si omis, SQL Server par défaut à l'aide de lamaster
base de données. Si l'ID utilisateur utilisé pour faire de la connexion JDBC seulement lepublic
rôle dans la base de données, la requête est exceptionnellement longue.Je ne sais pas pourquoi cela se produit. Cependant, je sais un autre plan de requête est utilisé dans de telles circonstances. J'ai confirmé ce à l'aide de l'outil générateur de profils SQL.
Détails de l'environnement:
OriginalL'auteur Mody
T-il un montant similaire de temps avec SQLWB? Si la version de Java est beaucoup plus lent, alors je voudrais vérifier un couple de choses:
OriginalL'auteur Brian Reiter