2010-10-08 9 views
2

J'ai un script PHP que vous pouvez télécharger des fichiers très volumineux avec (jusqu'à 500 Mo), et le contenu du fichier est stocké dans une base de données MySQL. Actuellement, je fais quelque chose comme ceci:Une meilleure façon de stocker de gros fichiers dans une base de données MySQL?

mysql_query("INSERT INTO table VALUES('')"); 

$uploadedfile = fopen($_FILES['file']['tmp_name'], 'rb'); 
while (!feof($uploadedfile)) { 
    $line = mysql_escape_string(fgets($uploadedfile, 4096)); 
    mysql_query("UPDATE table SET file = CONCAT(file, '$line') WHERE something = something"); 
} 
fclose($uploadedfile); 

Cela fait bien sûr beaucoup de requêtes sql.

Je l'ai fait plutôt que quelque chose comme

$file = file_get_contents($_FILES['file']['tmp_name']); 
mysql_query("INSERT INTO table VALUES('$file')"); 

parce que épuiserait cependant beaucoup de mémoire le fichier était, et il semblait préférable de faire plus de requêtes SQL que d'utiliser 500 Mo de mémoire.
Cependant, il doit y avoir un meilleur moyen. Dois-je aller de l'avant et le faire de manière file_get_contents ou y at-il un meilleur moyen que CONCAT, ou est-ce que je le fais maintenant le moindre de tous les maux?

+5

Je trouve en même temps intéressant et frustrant que chaque fois qu'une question est posée sur StackOverflow, beaucoup plus est dit sur la façon dont quelqu'un _should_ faire quelque chose plutôt sur _how_ faire ce qu'ils demandent. Les répondeurs doivent présenter des alternatives, et s'ils sont rejetés, essayez de répondre à la question posée. Peu importe pourquoi je dois le faire de cette façon. Je suis venu à StackOverflow pour obtenir une réponse à une question mais surtout je reçois juste des commentaires sur comment je ne devrais pas le faire de cette façon. –

+0

Si vous dites: «Je veux conduire ma voiture sur l'autoroute avec juste des jantes, pas de pneus. La réponse que la plupart des gens vous donneront est "Ne faites pas". Si vous demandez comment faire une bêtise avec du code, la plupart des dev qui connaissent leur truc répondront de la même manière. C'est une gentillesse, pas une insulte. – curtisdf

Répondre

3

Je stocke toujours mes fichiers sur le serveur et stocke leur emplacement dans la base de données.

+1

J'ai choisi les fichiers de stockage dans une base de données sql parce que cette option ne fonctionne pas pour moi. Je n'irais pas à tous ces problèmes si je pouvais juste l'enregistrer sur le disque. –

+1

@nickolas. Pourriez-vous expliquer pourquoi? Ma première pensée était les systèmes de fichiers sont bons pour le fichier ... –

+1

Bonne réponse. Stocker tout le fichier dans la table est comme garer votre voiture dans votre poche - mieux garer la voiture dans le garage et mettre la clé dans votre poche, même avec des fichiers, mieux pour stocker le fichier dans un dossier et son emplacement dans la table . –

0

Je voudrais imaginer que le moyen le plus efficace de faire cela serait de faire toute la validation dans le script jusqu'à l'insertion, puis de sortir et de faire un transfert de fichiers du fichier temporaire $ FILES téléchargé dans une requête d'insertion de ligne de commande MySQL. Vous voulez quelqu'un de mieux que moi pour valider cela, mais il semble que cela enlèverait à peu près le problème de mémoire?

1

Cela ne fonctionnerait pas réellement (par défaut) avec mySQl, car cela provoquerait une grosse requête de 500 Mo.

$file = file_get_contents($_FILES['file']['tmp_name']); 
mysql_query("INSERT INTO table VALUES('$file')"); 

parce que le max_allowed_packet est réglé sur 16777216. Vous soit demandé de l'augmenter ou le diviser en petits morceaux de 16 Mo (moins requête ~ 500-1000 octets pour la chaîne de requête).

Vous pouvez trouver le max_allowed_packet de votre serveur mysql en faisant l'interrogation

SELECT @@global.max_allowed_packet 
0

Je dois encore voir une application qui a réellement besoin de stocker des fichiers dans une base de données relationnelle.

Il existe un grand nombre de bases de données puissantes disponibles gratuitement et conçues et optimisées spécifiquement pour stocker/récupérer des fichiers. Ils sont appelés systèmes de fichiers

Stockez vos fichiers dans votre système de fichiers et vos métadonnées dans le SGBDR.

Vous vous inquiétez d'utiliser 500 Mo de mémoire lors de l'insertion, et on ne sait pas pourquoi. Vous allez finalement vouloir récupérer ces fichiers hors de la base de données, et je ne pense pas que vous trouverez un moyen de lire les données de fichier en morceaux.

+0

C'est une donnée. Il va dans la base de données. Au lieu de cela, vous préconisez de stocker certaines données dans un système et le reste dans un autre. Vous allez stocker des données dans deux systèmes parallèles. Vous avez donc le potentiel de désynchroniser ces deux systèmes. Vous avez deux points d'échec. Vous avez également le potentiel d'exploitation puisque votre application doit nécessairement être capable d'écrire dans le système de fichiers. Donc, il y a plus de potentiel pour écrire un exécutable qui est en quelque sorte exécuté. – Charles

+0

@Charles - Ce sont toutes les préoccupations valables. Cependant, d'après mon expérience, essayer de stocker une quantité importante de données BLOB dans le SGBDR conduit inévitablement à la douleur. Les systèmes de fichiers sont faciles à partitionner, faciles à répliquer/sauvegarder (rsync) et performants pour le cas d'utilisation. Ces jours-ci, vous pouvez utiliser quelque chose comme S3 et demander à quelqu'un d'autre de se préoccuper de la résilience et de la disponibilité. En d'autres termes, il y a une raison pour laquelle Amazon n'a pas implémenté S3 avec un SGBDR sur le back-end pour le stockage BLOB. – timdev

2

Vous avez raison, dans certains cas, un système de fichiers ne peut pas faire le travail. Parce que les bases de données ont des fonctionnalités telles que le verrouillage, la réplication, l'intégrité, pas de limitation sur le nombre de lignes, etc etc ... Qui n'existent pas dans un système de fichiers.

En outre, la sauvegarde/restauration/migrer le système devient plus complexe et ne peut se faire en toute sécurité sur un serveur exécutant (risque d'incohérence et la perte de données). Ou au moins garantir cela est très difficile dans une configuration DB + FS.

Qu'en est-il d'une migration «/» OS à base de séparation à un « \ » sur la base d'un? Vous devez mettre à jour tous vos chemins.

Votre méthode semble être correcte, mais le découpage en tranches de 4096 octets est trop petite. Mysql n'aura aucun problème à travailler avec des tranches de 256 Ko, par exemple.

De même, je ne voudrais pas concaténer, mais plutôt stocker chaque tranche comme un seul enregistrement. La base de données peut avoir des difficultés à stocker des fichiers volumineux dans un seul enregistrement, ce qui peut entraîner des limitations mentionnées dans d'autres réponses.

Garder les données en tranches permettra de streaming le contenu sans jamais stocker l'ensemble des données en mémoire, par exemple. De cette façon, il n'y a pratiquement aucune limite à la taille du fichier stocké.

Questions connexes