2010-08-05 6 views
-1

Je travaille sur une base de données, où le nombre de lignes est supérieur à 1 000 000. J'ai ma déclaration select, mais si je commence par fetchall, je manque de mémoire rapidement. Voici mes 2 questions:Perl DBI extrait une partie de la base de données?

  1. Depuis que je ne sais pas la taille exacte de la base de données pour commencer, est-il possible de connaître la taille de la base de données sans faire fetchall? L'ordinateur ne peut littéralement pas le supporter.

  2. Existe-t-il un moyen d'extraire un certain segment de la base de données, peut-être 5 000 à traiter au lieu de faire un fetchrow individuel pour chaque ligne? Je viens juste de terminer un test, et de le faire ligne par ligne, ça fait presque 4 minutes par 1000 lignes travaillées, et le patron ne regarde pas favorablement sur un programme qui va prendre presque 3 jours à compléter.

Ceci est mon code:

while ($i < $rows) 
{ 
    if ($i + $chunkRows < $rows) 
    { 
     for ($j = 0; $j < $chunkRows; $j++) 
     { 
      @array = $sth->fetchrow(); 
      ($nameOne, $numberOne, $numberTwo) = someFunction($lineCount,@array,$nameOne,$numberOne, $numberTwo); 
     } 
    } 
    else #run for loop for j < rows % chunkrows 
    $i = $i + $j 
} 
+0

Je veux retirer les lignes dans les paquets en espérant pouvoir réduire le temps perdu en appelant fetchRow sur plus d'un million de lignes individuelles. – ThePirateSheep

+0

Quelle base de données utilisez-vous? Différentes bases de données auront des réponses différentes à cette question. –

+0

J'utilise DBI, et les seules récupérations que je vois sont des constructeurs vides de fetchRow() et fetchall. Je cherche un fetchRows (0,5000) où 0 serait la ligne pour commencer, et 5000 serait le nombre de lignes à saisir ou quelque chose le long de ces lignes – ThePirateSheep

Répondre

0

Pour obtenir le nombre de lignes dans une table, vous pouvez utiliser

Select count(*) from Table

Pour limiter le nombre de lignes retournées, ce peut être spécifique à votre base de données. MySQL, par exemple, a un mot-clé Limit qui vous permettra de retirer seulement un certain nombre de lignes. Cela dit, si vous retirez toutes les lignes, vous voudrez peut-être ajouter d'autres questions décrivant précisément ce que vous faites, car ce n'est pas une chose courante dans la plupart des applications.

Si vous ne disposez pas d'un limit disponible dans votre base de données, vous pouvez par exemple marquer une colonne avec un booléen pour indiquer qu'une ligne a été traitée, puis réexécuter votre requête pour un nombre limité de lignes, en ignorant qui ont été complétés. Ou enregistrez la dernière ligne identifiée, puis limitez votre prochaine requête aux lignes avec un identifiant supérieur. Il y a beaucoup de façons de contourner cela.

+0

Donc J'ai fini par me frayer un chemin à travers le compte, ce qui rend ma vie un peu plus facile. J'ai eu un compte de sélection (1) en cours, mais je n'ai jamais syntaxé correctement. Je ne crois pas qu'il y ait un mot-clé de type limite dans DBI, ce que j'utilise. Aussi, je n'ai pas l'accès pour mettre à jour la base de données, puisque ces données proviennent d'une source extérieure. En regardant comment la base de données est et comment elle est triée, la seule chose qui est dans un ordre (comme l'ID de ligne ou quelque chose) est un horodatage, mais il peut y avoir plusieurs horodateurs identiques dans la base de données. Je cherche un fetch (0,5000) à partir de 0 et en prenant 5000 – ThePirateSheep

+0

Ma pensée est que la raison pour laquelle le programme prend 3 jours est due au fait que chaque fetch est individuel, et chaque fois qu'il est appelé, il est la majeure partie de ma latence et du temps passé. Je ne sais pas si je l'explique du mieux que je peux:/ – ThePirateSheep

+1

DBI n'est pas une base de données, c'est l'interface * de la base de données perl. Ce que vous voulez rechercher est de voir si le serveur de base de données auquel vous vous connectez a un mot-clé LIMIT. Quel serveur de base de données utilisez-vous? Si vous ne pouvez pas écrire dans la base de données ... pouvez-vous écrire dans un fichier? Interrogez les lignes, écrivez les informations dans un fichier, puis traitez chaque ligne dans le fichier. Cela pourrait réduire l'utilisation de la mémoire. Ou, faites de même pour une deuxième table à laquelle vous avez un accès en écriture. – GrandmasterB

1

Afficher votre code de boucle fetchrow; Il peut y avoir des façons de l'améliorer, selon la façon dont vous l'appelez et ce que vous faites avec les données. Je crois que les pilotes de base de données pour la plupart des bases de données vont chercher plusieurs lignes à la fois à partir du serveur; vous allez devoir dire quel type de base de données vous utilisez pour obtenir de bons conseils. Si en effet il communique avec le serveur pour chaque ligne, vous devrez modifier le SQL pour obtenir des ensembles de lignes à la fois, mais comment faire cela varie selon la base de données que vous utilisez.

Ah, DB2. Je ne suis pas sûr, mais je pense que vous devez faire quelque chose comme ceci:

SELECT * 
FROM (SELECT col1, col2, col3, ROW_NUMBER() OVER() AS RN FROM table) AS cols 
WHERE RN BETWEEN 1 AND 10000; 

et changer les chiffres pour chaque requête jusqu'à ce que vous obtenez un résultat vide. Évidemment, cette est plus de travail sur le côté de la base de données pour avoir répéter la requête plusieurs fois; Je ne sais pas s'il existe des moyens DB2 pour optimiser cela (c'est-à-dire des tables temporaires).

Questions connexes