2010-11-10 29 views
1

J'ai quelques procédures Oracle qui génèrent/retournent une grande quantité de données que j'ai besoin d'écrire dans un fichier. J'essaye actuellement d'accomplir avec un lecteur de données. Il semble fonctionner, j'ai réussi à générer un fichier 479mb sans aucun problème. Il a fallu moins de 4 minutes à partir du moment où j'ai récupéré le dataReader pour terminer le fichier.Problèmes de grande performance avec Oracle DataReader dans .Net

Mais le dataReader que je reçois pour une procédure particulière est crawl. C'est incroyablement lent. J'ai modifié mon code pour essayer d'obtenir une meilleure idée de ce qui se passe ....

System.Diagnostics.Debug.Write("Performing .Read() on DataReader: ") 
Dim d1 As DateTime = DateTime.Now 
Dim result As Boolean = myDataReader.Read() 
Dim ts As TimeSpan = DateTime.Now.Subtract(d1) 
System.Diagnostics.Debug.WriteLine(ts.ToString) 

L'intéressant est que ma sortie finit par ressembler à ceci:

Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:00:00 
Performing .Read() on DataReader: 00:07:33.5037500 

Je suis vraiment à court de quoi faire ensuite. Je ne peux pas voir quelque chose d'unique ou de différent sur la ligne qui prend 07: 33.5037500. Aucune suggestion?

EDIT:

Merci pour tout le monde réponses. Premièrement, du mieux que je sache, aucune exception n'est levée. Comme suggéré, j'ai jeté un oeil à cette procédure particulière qui expose le comportement ci-dessus et tandis que la procédure est ridiculement massive; mais il semble qu'il utilise beaucoup de curseurs pour remplir une table temporaire Oracle. Le curseur de référence renvoyé est un SELECT * FROM de cette table temporaire.

Je suis en train d'écrire un bloc PL/SQL qui va ouvrir ce curseur pour voir si le problème de performance existe lorsque je supprime le code .Net ... j'espère que cela aidera; mais si vous avez d'autres idées, ce sera très apprécié.

Merci encore une fois. Cela semble être un problème PL/SQL et pas un problème .NET.

+2

pas assez d'informations pour répondre à l'atm ... sauf si elle lance des exceptions qui sont traitées silencieusement? –

+0

vous devriez probablement poster plus de votre code complet ... –

Répondre

3

Que fait réellement la base de données?

Une requête avec GROUP BY ou ORDER BY peut nécessiter la génération de l'ensemble de résultats complet, puis le trier/l'agréger avant de renvoyer une ligne. Une requête analysant une grande table peut trouver 50 lignes dans les deux premiers blocs, puis lire une autre centaine de blocs avant d'en trouver une autre.

Je vous suggère d'ignorer le code VB et d'afficher le code de la base de données.

+0

La procédure est ridiculement massive; mais il semble qu'il utilise beaucoup de curseurs pour remplir une table temporaire Oracle. Le curseur de référence renvoyé est un SELECT * FROM de cette table temporaire. –

+0

Ensuite, je pense que vous pouvez à peu près garantir que le problème est quelque part dans le code PL/SQL et les requêtes. Demandez à votre administrateur de base de données de vous aider à entrer dans les détails. –

2

Je suppose que lorsque vous dites "procédure particulière", vous voulez dire que vous appelez une procédure stockée Oracle qui a un paramètre OUT qui est un REF CURSOR. Votre DataReader récupère ensuite à partir du curseur renvoyé par la procédure. Est-ce le cas?

Si oui, pouvez-vous éliminer le code .Net et écrire un bloc PL/SQL qui appelle la procédure et récupère toutes les données du curseur pour voir si vous obtenez le même comportement là-bas? Oracle ne matérialise pas les données lorsque le curseur est ouvert: il matérialise les résultats lorsque le client récupère les données. Il est donc possible qu'Oracle doive faire un peu de travail pour aller chercher la Nième ligne si elle doit se matérialiser et filtrer un tas de données avant de trouver la N + 1ème ligne. Si vous voyez le même comportement dans PL/SQL s'exécuter sur la base de données, c'est certainement ce qui se passe. Si vous ne voyez aucun problème dans le bloc PL/SQL, alors quelque chose doit se passer dans le niveau intermédiaire.

+0

Merci - oui c'est un param OUT qui est un CURSEUR REF. Je vais l'essayer en PL/SQL et comparer. –

1

Juste quelques commentaires généraux, pour la version originale de votre question:

Si vous utilisez Microsoft.Les classes fournisseur System.Data.OracleClient de NET Framework, vous pourriez obtenir de meilleures performances de Oracle's own updated .NET Provider. Si le temps passe autour de chaque exécution, le garbage collector .NET utilise peut-être une partie de l'utilisation de la mémoire qui n'est pas visible dans votre exemple (c'est-à-dire si plusieurs objets sont instanciés et jetés).