2010-10-29 2 views
3

J'ai un fichier csv avec les enregistrements en cours de tri sur le premier champ. J'ai réussi à générer une fonction qui effectue une recherche binaire à travers ce fichier, en utilisant fseek pour un accès aléatoire par fichier.fichier php accès aléatoire et objet à enregistrer fichier

Cependant, c'est encore un processus assez lent, puisque lorsque je cherche une position de fichier, j'ai vraiment besoin de regarder à gauche, à la recherche de \ n caractère, afin que je puisse lire toute une ligne la ligne est lue, je peux vérifier la première valeur de champ mentionnée ci-dessus).

Voici la fonction qui renvoie une ligne qui contient le caractère à la position x:

 

function fgetLineContaining($fh, $x) { 
     if($x 125145411) // 12514511 is the last pos in my file 
      return ""; 
     // now go as much left as possible, until newline is found 
     // or beginning of the file 
     while($x > 0 && $c != "\n" && $c != "\r") { 
      fseek($fh, $x); 
      $x--; // go left in the file 
      $c = fgetc($fh); 
     } 
     $x+=2; // skip newline char 
     fseek($fh, $x); 
     return fgets($fh, 1024); // return the line from the beginning until \n 
    } 
 

Bien que cela fonctionne comme prévu, je dois triste que mon fichier csv a ~ lignes de 1.5mil, et ces recherches de gauche ralentissent à peu près.

Existe-t-il un meilleur moyen de rechercher une ligne contenant la position x dans un fichier?

De même, il serait préférable qu'un objet d'une classe puisse être sauvegardé dans un fichier sans le sérialiser, permettant ainsi la lecture d'un fichier objet par objet. Est-ce que php supporte cela?

Merci

+0

également, une autre idée m'est venue à l'esprit - que diriez-vous de l'échantillonnage d'un fichier - prendre une entrée pour 1000 entrées du fichier et le stocker dans le tableau. cela produirait 1500 array d'éléments, que je pourrais rechercher binaire, obtenant l'approximation approximative où la ligne désirée est. Je pourrais alors charger les 1000 éléments restants et faire une recherche binaire sur eux. est-ce que ça fait la même chose? – hummingBird

+1

Quel genre de recherches effectuez-vous sur ce fichier? Est-ce que le fichier change fréquemment? Si vous effectuez de nombreuses recherches sur le même fichier, il peut être beaucoup plus rapide de simplement charger les données dans une base de données SQLite et de rechercher dans la base de données. – kijin

+1

Si vous connaissez la longueur d'une ligne moyenne, vous pouvez simplement revenir en arrière et faire 'fgets()' pour aligner le pointeur avec la fin de la ligne précédente, ou quelques lignes avant cela. Devrait être assez bon dans le but de la recherche binaire. – kijin

Répondre

1

Je pense que vous devriez vraiment envisager d'utiliser SQLite ou MySQL à nouveau (comme d'autres ont suggéré dans les commentaires). La plupart des suggestions sur les index de pré-calcul sont déjà implémentées "correctement" dans ces moteurs SQL.

Vous avez dit que la vitesse n'était pas assez bonne en SQL. Avez-vous les champs indexés correctement? Comment avez-vous interrogé les données? Où vous utilisez des requêtes en bloc, où vous utilisez des instructions préparées? Le processus SQL a-t-il suffisamment de RAM pour stocker ses index en RAM?

Une chose que vous pouvez essayer d'accélérer sous l'algorithme actuel est de charger le fichier (~ 100 Mo?) Sur un disque RAM. Peu importe ce que vous avez choisi de faire, CVS ou SQLite, cela aidera à accélérer les choses, surtout si le temps de recherche de disque dur est votre goulot d'étranglement.

Vous pourriez même lire tout le fichier dans les tableaux PHP (en supposant que votre ordinateur dispose de suffisamment de RAM pour cela). Cela vous permettrait de faire votre recherche via les recherches index ($big_array[$offset]).

Aussi une chose à garder à l'esprit, PHP n'est pas exactement super rapide à faire des choses de bas niveau rapidement. Vous pourriez envisager de s'éloigner de PHP en faveur de C ou C++.

+0

Eh bien, sql partie de cette question se trouve sous des questions de prime, à ce lien (http://stackoverflow.com/questions/4007671/effective-ip-location-query). Je n'ai pas d'expérience en optimisation mysql, et je dois dire que je ne connais pas de réponse à toutes vos questions. – hummingBird

+0

peut-être un plus petit db ferait le travail ??? – hummingBird

+0

J'ai réussi à obtenir 3-4 fois l'accélération en utilisant 2 fichiers supplémentaires avec une sorte de recherche binaire :) – hummingBird

Questions connexes