2017-05-31 2 views
1

En PHP, j'utilise fopen(), , et fclose() pour lire un fichier ligne par ligne. Ça marche bien. Mais j'ai un script (exécuté à partir de la CLI) qui doit traiter trois centaines de fichiers texte de 5 Go. C'est environ 3 milliards fgets(). Donc, cela fonctionne assez bien, mais à cette échelle, les économies de vitesse minuscules vont s'accumuler extrêmement vite. Alors je me demande s'il y a des astuces pour accélérer le processus?Manière plus rapide de lire le fichier ligne par ligne?

La seule chose à laquelle je pensais était d'obtenir fgets() pour lire plus d'une ligne à la fois. Il ne semble pas que cela prenne en charge cela, mais je pourrais en théorie dire 20 consécutifs $line[] = fgets($file); puis traiter le tableau. Ce n'est pas tout à fait la même chose que de lire plusieurs lignes dans une même commande, cela n'a donc aucun effet. Mais je sais mettre en file d'attente vos insertions mysql et les envoyer comme un insert géant (une autre astuce que je vais mettre en œuvre dans ce script après plus de tests et de benchmarking) permettra d'économiser beaucoup de temps.

+0

Vous pourriez essayer de le lire "buffer by buffer" et de regrouper les lignes splitées – modsfabio

+0

Avez-vous essayé d'utiliser la fonction fgetcsv? –

+0

mmap ou createfilemapping pour le script PHP sera utile https://github.com/calcinai/php-mmap – tommybee

Répondre

0

Une approche possible qui pourrait être plus rapide serait de lire de gros morceaux du fichier avec fread(), de le diviser par des retours à la ligne, puis de traiter les lignes. Vous devez prendre en compte le fait que les morceaux peuvent couper des lignes et vous devez le détecter et les recoller ensemble. En règle générale, plus le morceau que vous pouvez lire en une seule fois est important, plus votre processus devrait devenir rapide. Dans les limites de votre mémoire disponible.

De fread() docs:

Notez que fread() lit de la position actuelle du pointeur de fichier. Utilisez ftell() pour trouver la position actuelle du pointeur et rembobinez() pour rembobiner la position du pointeur.

+0

Comment pourrais-je faire face à des lignes de split? Je suppose que je pourrais juste sauvegarder tout ce qui vient après la dernière 'nouvelle ligne' à l'arrière, et le coller au début de la prochaine lecture. Comment dites-vous à fread() où lire? Ou comme les fgets, va-t-il toujours s'auto-incrémenter à travers le fichier pendant que vous continuez à l'appeler? – l008com

+0

@ l008com Oui. vous auriez besoin d'une variable pour stocker tout ce qui vient après la dernière ligne de retour et la combiner avec tout ce qui est arrivé avant le premier saut de ligne du morceau suivant. – Kempeth