Comment puis-je améliorer mon instruction INSERT de performance?

Tandis que Josh réponse ici m'a donné une bonne longueur d'avance sur la façon d'insérer une 256x64x250 tableau de valeur dans une base de données MySQL. Quand j'ai essayé de son instruction INSERT sur mes données, il s'est avéré horriblement lent (comme dans 6 minutes pour un 16 mo de fichier).

ny, nx, nz = np.shape(data)
query = """INSERT INTO `data` (frame, sensor_row, sensor_col, value) VALUES (%s, %s, %s, %s)"""
for frames in range(nz):
    for rows in range(ny):
        for cols in range(nx):
            cursor.execute(query, (frames, rows, cols, data[rows,cols,frames]))

Je lisais MySQL pour Python, qui a expliqué que ce n'était pas la bonne approche, car l'exécution de 4 millions de séparer les plaquettes est très inefficace.

Maintenant mes données se composent de beaucoup de zéros (plus de 90% en fait), donc je l'ai jeté dans une instruction if donc, je n'insérez des valeurs supérieures à zéro et j'ai utilisé executemany() à la place:

query = """INSERT INTO `data` (frame, sensor_row, sensor_col, value) VALUES (%s, %s, %s, %s ) """
values = []
for frames in range(nz):
    for rows in range(ny):
        for cols in range(nx):
            if data[rows,cols,frames] > 0.0:
                values.append((frames, rows, cols, data[rows,cols,frames]))           
cur.executemany(query, values)

Ce miraculeusement apporté mon temps de traitement jusqu'à environ 20 secondes, dont 14 secondes passent sur la création de la liste de valeurs (37k lignes) et 4 secondes sur la réelle insertion dans la base de données.

Alors maintenant, je me demandais, comment puis-je accélérer ce processus davantage? Parce que j'ai le sentiment que ma boucle est horriblement inefficace et il y a une meilleure façon. Si j'ai besoin d'insérer des 30 mesures par chien, ce serait encore prendre 10 minutes, ce qui semble beaucoup trop long pour cette quantité de données.

Voici deux versions de mes fichiers raw: avec les en-têtes ou sans les en-têtes. J'aimerais essayer de le LOAD DATA INFILE, mais je ne peux pas comprendre comment analyser correctement les données.

  • D'où viennent les données?
  • C'est un gros fichier texte avec des en-têtes au-dessus de chaque cadre, qu'est-ce précisément que vous voulez savoir?
  • Je suis juste curieux de savoir si le long processus de la prise de est de la lecture du fichier ou les boucles for imbriquées pour créer la requête.
  • Qu'est-ce que data? Peut-être que vous pouvez obtenir values par l'application d'une fonction sur data? Cela pourrait vous donner des principaux speedup.
  • de données est un tableau numpy, qui est chargé dans la mémoire, donc je suppose qu'il s'agit de boucles imbriquées. Si il y a un autre moyen de récupérer toutes les non-valeurs zéro avec leurs index, alors je suis tout ouïe
  • Gardez à l'esprit que le plus de [INSÉRER] les opérations sont effectuées, la probabilité de performances seront un sujet de préoccupation. Les bases de données d'écriture sur le disque - alors qu'il y a un tampon, il peut être épuisé. Aussi, vous voudrez peut-être regarder dans le MySQL LOAD DATA INFILE pour le chargement de fichiers, mais je ne pense pas qu'il prend en charge la logique de décision que vous utilisez pour lancer des données (pourquoi est-il connecté en premier lieu?).
  • les données sont exportées à partir d'un autre logiciel, donc je n'ai pas d'influence sur le format. Je peux imaginer que le chargement d'un fichier directement dans la base de données serait encore plus vite, mais je ne suis pas sûr de savoir comment assurez-vous qu'il a le bon format.
  • J'ai ajouté une modification à ma réponse originale à cette question qui pourrait être d'intérêt.
  • numpy.nonzero()

InformationsquelleAutor Ivo Flipse | 2011-03-27