Salut,

Je rencontre un problème avec symfony et plus particulièrement Doctrine. En fait, je voudrais récupérer une "grosse" quantité (elle me semble pas si énorme que cela à mes yeux ...) de données afin de les exporter dans un fichier CSV.

J'ai 4 table liées entres-elles à récupérer : une Participation "has many" Newsletters, Fields et Questions.

Voilà le schéma correspondant aux 4 tables :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
QuizgenParticipation:
  actAs: { Timestampable: ~ }
  columns:
    quiz_id:      { type: integer, notnull: true }
    civility:     { type: string(255), notnull: true }
    birthdate:    { type: timestamp, notnull: true }
    firstname:    { type: string(255), notnull: true }
    lastname:     { type: string(255), notnull: true }
    city:         { type: string(255), notnull: true }
    zip_code:     { type: string(255), notnull: true }
    email:        { type: string(255), notnull: true }
    accept_rules: { type: boolean, notnull: true, default: NULL }
    shares:       { type: integer, notnull: true, default: 0 }
  relations:
    QuizgenQuiz: { onDelete: CASCADE, local: quiz_id, foreign: id, foreignAlias: QuizgenParticipations } 
    QuizgenNewsletters:
      class: QuizgenNewsletter
      refClass: QuizgenParticipationNewsletter
      local: participation_id
      foreign: newsletter_id
      foreignAlias: QuizgenParticipations
    QuizgenFields:
      class: QuizgenField
      refClass: QuizgenParticipationField
      local: participation_id
      foreign: field_id
      foreignAlias: QuizgenParticipations      
    QuizgenQuestions:
      class: QuizgenQuestion
      refClass: QuizgenParticipationQuestion
      local: participation_id
      foreign: question_id
      foreignAlias: QuizgenParticipations 
 
QuizgenParticipationQuestion:
  columns:    
    participation_id:  { type: integer, notnull: true }
    question_id:       { type: integer, notnull: true }
    answer:            { type: string(255), notnull: true }
  relations:
    QuizgenParticipation: { onDelete: CASCADE, local: participation_id, foreign: id }     
    QuizgenQuestion:      { onDelete: CASCADE, local: question_id, foreign: id }   
 
QuizgenParticipationNewsletter:
  columns:    
    participation_id:  { type: integer, notnull: true }
    newsletter_id:     { type: integer, notnull: true }
  relations:
    QuizgenParticipation: { onDelete: CASCADE, local: participation_id, foreign: id }     
    QuizgenNewsletter:    { onDelete: CASCADE, local: newsletter_id, foreign: id }
 
QuizgenParticipationField:
  columns:    
    participation_id:  { type: integer, notnull: true }
    field_id:          { type: integer, notnull: true }
    value:             { type: string(255) }
  relations:
    QuizgenParticipation: { onDelete: CASCADE, local: participation_id, foreign: id }     
    QuizgenField: { onDelete: CASCADE, local: field_id, foreign: id }
Comme vous vous en doutez, QuizgenParticipationField, QuizgenParticipationNewsletter et QuizgenParticipationQuestion sont liés à d'autres infos, mais je n'en ai pas besoin ici.

Il y aura entre 1000 et 5000 participations à exporter. Chaque participation est suceptible de posséder environ une 10aine de questions, 3 champs et 3 newsletters.

J'ai donc optimisé ma requete DQL en faisant des leftJoin pour n'avoir qu'une seule requête de générée. J'ai également hydraté cela en tableau :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 public function getParticipationsForQuiz($quizId)
  {
    $q = $this->createQuery('p INDEXBY p.id')
      ->where('p.quiz_id = ?', $quizId)
      ->leftJoin('p.QuizgenParticipationField pf INDEXBY pf.field_id')
      ->leftJoin('p.QuizgenParticipationNewsletter pn INDEXBY pn.newsletter_id')
      ->leftJoin('p.QuizgenParticipationQuestion pq')
      ->orderBy('p.id');
 
      return  $q->execute(array(),Doctrine::HYDRATE_ARRAY);
  }
Le problème,c 'est que malgré ça, pour seulement 800 participations (10 questions pour chaque participation), ça me prend 23 secondes d'execution et 37Mo en mémoire ! Mais il ne m'est pas possible de dépasser 16Mo de mémoire.

Qu'est ce qui n'est pas correct dans ce que j'ai fait ? Comme se fait-il que ma requête nécessite autant de mémoire ?

Merci d'avance pour votre aide !