Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 8 sur 8
  1. #1
    Nouveau Membre du Club
    Inscrit en
    avril 2006
    Messages
    71
    Détails du profil
    Informations forums :
    Inscription : avril 2006
    Messages : 71
    Points : 33
    Points
    33

    Par défaut [Insert] Importation massive de données sans COPY FROM fichier, ni psql

    Bonjour à tous,

    Jusqu’à présent, je pouvais téléverser des fichiers (environ 100 000 lignes) directement dans ma base de données, en lançant la commande COPY sur un fichier CSV, grâce à psql :

    Code :
    copy matable (column1, column2, column3, … columnN) FROM 'monfichier.csv'  delimiter ',' csv header
    Seulement, voilà, mon hébergeur a soudainement décidé qu’on ne pourrait plus lancer psql à partir de PHP (exec). Je ne peux pas non plus lancer la commande COPY FROM avec PDO.

    Que me reste-t-il comme solution pour importer massivement des données à partir de PHP ?

    Générer une méga-requête avec PHP ?

    Un massif
    Code :
    1
    2
    3
    4
    5
    6
    INSERT INTO matable (column1, … columnN) VALUES
        ('value1', … 'valueN'),
        ...
        [100 000 lignes]
        ...
        ('value1', … 'valueN');
    est-il envisageable ?

    Quelle est la limite théorique de ce genre d’insertions par lot ?

    Y a-t-il une meilleure méthode ?

    Config : PostgreSQL 8.4, sur serveur Apache (Ubuntu).

    Merci d’avance.

  2. #2
    Expert Confirmé
    Profil pro
    Inscrit en
    octobre 2008
    Messages
    1 818
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 818
    Points : 2 505
    Points
    2 505

    Par défaut

    L'interface non-PDO de php permet de faire du COPY avec pg_copy_from et pg_copy_to

  3. #3
    Nouveau Membre du Club
    Inscrit en
    avril 2006
    Messages
    71
    Détails du profil
    Informations forums :
    Inscription : avril 2006
    Messages : 71
    Points : 33
    Points
    33

    Par défaut

    Merci pour la réponse.

    Toutefois pg_copy_from fait une copie à partir d’une table, pas à partir d’un fichier.

    C’est quand même mieux que la solution que j’avais en tête, car je peux importer un fichier dans une table avec la commande file, mais 100 000 entrées en mémoire avant de les insérer dans la base, ça me semble un peu volumineux, surtout que le chiffre 100 000 pourrait éventuellement décupler.

    Quelqu’un a une meilleure solution ?

  4. #4
    Expert Confirmé
    Profil pro
    Inscrit en
    octobre 2008
    Messages
    1 818
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 818
    Points : 2 505
    Points
    2 505

    Par défaut

    Citation Envoyé par MorganStern Voir le message

    C’est quand même mieux que la solution que j’avais en tête, car je peux importer un fichier dans une table avec la commande file, mais 100 000 entrées en mémoire avant de les insérer dans la base, ça me semble un peu volumineux, surtout que le chiffre 100 000 pourrait éventuellement décupler.
    Regarde l'exemple de la doc de php:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php 
      $conn = pg_pconnect("dbname=foo");
      pg_query($conn, "create table bar (a int4, b char(16), d float8)");
      pg_query($conn, "copy bar from stdin");
      pg_put_line($conn, "3\tBonjour le monde\t4.5\n");
      pg_put_line($conn, "4\tAurevoir le monde\t7.11\n");
      pg_put_line($conn, "\\.\n");
      pg_end_copy($conn);
    ?>
    Tu peux l'adapter facilement avec une boucle autour de pg_put_line() qui lirait le fichier ligne par ligne avec fgets() et dans ce cas il n'y a quasiment pas de consommation de mémoire.

  5. #5
    Expert Confirmé
    Profil pro
    Inscrit en
    octobre 2008
    Messages
    1 818
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 818
    Points : 2 505
    Points
    2 505

    Par défaut

    Autre méthode: la commande que tu cites initialement est COPY c.a.d une commande SQL et non pas une commande spécifique psql, sinon ce serait \copy.
    En fait la commande COPY est accessible aussi en php via pg_query() comme n'importe quelle autre commande SQL. Elle implique simplement que le fichier va être ouvert par le serveur postgres lui-même, donc il faut qu'il lui soit accessible avec ses droits à lui.
    Mais si cette partie-là fonctionnait déjà avant, pas de raison qu'elle ne fonctionne plus même sans psql.

  6. #6
    Nouveau Membre du Club
    Inscrit en
    avril 2006
    Messages
    71
    Détails du profil
    Informations forums :
    Inscription : avril 2006
    Messages : 71
    Points : 33
    Points
    33

    Par défaut

    Bonsoir,

    Je crains d’avoir été imprécis. C’est la commande \copy que j’utilisais avec psql et non COPY. La commande COPY FROM a été restreinte dans PostgreSQL (qui me disait justement d’utiliser psql \copy, mais à présent que exec est proscrit aussi, ça complique l’affaire).

    Je vais voir demain si COPY FROM marchera avec pg_query. (Le commentaire de la doc semble dire que oui… c’est curieux…).

    Quoi qu’il en soit, merci pour l’aide.

  7. #7
    Expert Confirmé
    Profil pro
    Inscrit en
    octobre 2008
    Messages
    1 818
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 818
    Points : 2 505
    Points
    2 505

    Par défaut

    c'est COPY FROM fichier qui est réservé aux profils postgres "superuser", mais pas COPY FROM STDIN qui est d'ailleurs la commande utilisée en sous-main par le \copy de psql.

  8. #8
    Nouveau Membre du Club
    Inscrit en
    avril 2006
    Messages
    71
    Détails du profil
    Informations forums :
    Inscription : avril 2006
    Messages : 71
    Points : 33
    Points
    33

    Par défaut

    Merci beaucoup pour ton aide et les précisions fort utiles.

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •