web-dev-qa-db-fra.com

Pandas SQL chunksize

Il s'agit plus d'une question de compréhension que de programmation. Je suis assez nouveau pour Pandas et SQL. J'utilise pandas pour lire les données de SQL avec une taille de bloc spécifique. Lorsque j'exécute une requête SQL, par exemple import = pandas as pd

df = pd.read_sql_query('select name, birthdate from table1', chunksize = 1000)

Ce que je ne comprends pas, c'est que lorsque je ne donne pas de taille de bloc, les données sont stockées dans la mémoire et je peux voir la mémoire augmenter cependant, quand je donne une taille de bloc, l'utilisation de la mémoire n'est pas si élevée.

J'ai est que ce df contient maintenant un certain nombre de tableaux auxquels je peux accéder en tant que

for df_array in df:
    print df.head(5)

Ce que je ne comprends pas ici, c'est si tout le résultat de l'instruction SQL est conservé en mémoire, c'est-à-dire que df est un objet portant plusieurs tableaux ou s'il s'agit de pointeurs pointant vers une table temporaire créée par une requête SQL.

Je serais très heureux de mieux comprendre comment ce processus fonctionne réellement.

18
Nitin Kumar

Examinons deux options et ce qui se passe dans les deux cas:

  1. chunksize est None (valeur par défaut):
    • pandas passe la requête à la base de données
    • la base de données exécute la requête
    • pandas vérifie et voit que chunksize est None
    • pandas indique à la base de données qu'il souhaite recevoir toutes les lignes du tableau de résultats en même temps
    • la base de données renvoie toutes les lignes de la table de résultats
    • pandas stocke la table de résultats en mémoire et l'enveloppe dans une trame de données
    • vous pouvez maintenant utiliser le bloc de données
  2. chunksize in not None:
    • pandas passe la requête à la base de données
    • la base de données exécute la requête
    • pandas vérifie et voit que chunksize a une certaine valeur
    • pandas crée un itérateur de requête (boucle habituelle 'while True' qui se casse lorsque la base de données indique qu'il ne reste plus de données) et itère dessus chaque fois que vous voulez le prochain morceau de la table de résultats
    • pandas dit à la base de données qu'il souhaite recevoir des lignes de grande taille
    • la base de données retourne les prochaines lignes de morceaux de la table de résultats
    • pandas stocke les prochaines rangées de morceaux en mémoire et les enveloppe dans une trame de données
    • vous pouvez maintenant utiliser le bloc de données

Pour plus de détails, vous pouvez voir le module pandas\io\sql.py , il est bien documenté

25
prusya

Lorsque vous ne fournissez pas de chunksize, le résultat complet de la requête est placé dans une trame de données à la fois.

Lorsque vous fournissez un chunksize, la valeur de retour de read_sql_query Est un itérateur de plusieurs trames de données. Cela signifie que vous pouvez parcourir cela comme:

for df in result:
    print df

et à chaque étape df est un cadre de données (pas un tableau!) qui contient les données d'une partie de la requête. Voir les documents à ce sujet: http://pandas.pydata.org/pandas-docs/stable/io.html#querying

Pour répondre à votre question concernant la mémoire, vous devez savoir qu'il existe deux étapes pour récupérer les données de la base de données: execute et fetch.
La requête est d'abord exécutée (result = con.execute()), puis les données sont extraites de cet ensemble de résultats sous la forme d'une liste de tuples (data = result.fetch()). Lors de la récupération, vous pouvez spécifier le nombre de lignes que vous souhaitez récupérer simultanément. Et c'est ce que fait pandas lorsque vous fournissez un chunksize.
Mais, de nombreux pilotes de base de données mettent déjà toutes les données en mémoire dans l'étape d'exécution, et pas seulement lors de la récupération des données. À cet égard, cela ne devrait donc pas avoir beaucoup d'importance pour la mémoire. Mis à part le fait que la copie des données dans un DataFrame se produit uniquement en différentes étapes lors de l'itération avec chunksize.

20
joris