Учение гнездится несколькими объединениями - PullRequest
0 голосов
/ 27 марта 2011

Я пытаюсь оптимизировать приложение Symfony с помощью Doctrine.Я наткнулся на следующую проблему:

В представлении я использовал $ project-> getProgress ();но благодаря этому количество запросов увеличивается по мере увеличения количества проектов.Поэтому я попытался поместить прогресс в запрос проектов (переопределив метод findAll) с помощью левого соединения, но это не сработало.Количество запросов фактически увеличилось.

public function findAll($hydrationMode = null)
{
    $q = $this->createQuery('p')
                    ->leftJoin('p.progress pr')
                    ->leftJoin('pr.sfGuardUser u')
                    ->leftJoin('p.raws r')
                    ->leftJoin('p.series');
    return $q->execute(array(), $hydrationMode);
}

Это результат, который я пытаюсь создать с минимально возможным количеством запросов:

array() {
  [0]=>
  array() {
    ["id"]=> string(1) "1"
    ...
    ["progress"]=>
    array() {
        array() {
            array() { progress1 }
            array() { progress2 }
            array() { progress3 }
            ....
        }
    }
  }

Я просмотрел документациюи Symfony и Doctrine и не могли найти мой ответ.Я также долго искал в Google.(Я искал решение уже несколько месяцев). Надеюсь, я достаточно хорошо описал свою проблему.

schema.yml:

projects:
  actAs:
    Timestampable: ~
  columns:
    user_id: integer(4)
    series_id: bigint
    pages: int
    chapter: string
    translators_id: bigint
    proofreaders_id: bigint
    cleaners_id: bigint
    typesetters_id: bigint
    raws_id: bigint
    hide_project: bool
    complete: bool
  relations:
    sfGuardUser:
      local: user_id
      foreign: id
      onDelete: CASCADE
    series:
      local: series_id
      foreign: id
      type: one
      foreignType: many
      onDelete: CASCADE
    progress:
      local: id
      foreign: projects_id
      onDelete: CASCADE
      type: one
      foreignType: many

projectsProgress:
  actAs: [Timestampable]
  columns:
    projects_id: bigint
    user_id: integer(4)
    job:
      type: enum
      notnull: true
      values: [tl,pr,cl,ts]
    beginpage: int
    endpage: int
    complete: bool
    file: string
    url: clob
  relations:
    sfGuardUser:
      local: user_id
      foreign: id
      onDelete: CASCADE
    projects:
      local: projects_id
      foreign: id
      onDelete: CASCADE
      foreignAlias: progress

Ответы [ 2 ]

0 голосов
/ 27 марта 2011

Проблема использования гидратного режима заключается в том, что вы можете получать данные, которые не будут использоваться.Я действительно не знаю, как доктрина извлекает все данные, но предполагаю, что для каждого проекта приносит все необходимые данные, добавляя, по крайней мере, еще один запрос ...

Для сложных запросов (и оптимизации) я предпочитаю делать руководствозапросить и собрать все необходимые данные в одном запросе, например:

$query = "SELECT ... FROM projects p LEFT JOIN progress pr (LEFT JOIN sfGuardUser u (LEFT JOIN...) ON pr.user_id = u.id ) ON p.id = pr.projects_id"

$rs = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query);

, являющийся $ rs массивом с выбранными данными.Имея все данные, вы можете создать массив так, как вам нравится, но помните, что таким образом вы делаете один запрос (уменьшая нагрузку на БД), но добавляете некоторое время, анализирующее массив.

0 голосов
/ 27 марта 2011

Вам нужно изменить запрос, который выбирает объект Project, чтобы включить объединения. Обычно запросы, извлекающие Project объекты, должны быть помещены в ProjectTable.

Если вы хотите изменить все запросы или подмножества запросов Project, изучите Прослушиватели выполнения запросов Doctrine .

...