Могу ли я сократить количество запросов к БД, которые CakePHP делает здесь? - PullRequest
2 голосов
/ 06 июля 2011

Итак, у меня есть запрос Cake, который выглядит примерно так:

$forthcomingReleases = $this->Release->find('all', array(
        'contain'=>array('Artist.name', 'Artist.slug', 'Releasetype.type', 'Format.Mediatype.name'),
        'conditions'=>array('release_date >' => date('Ymd'), 'Release.is_deleted' => false),                
        'order'=>array('release_date DESC'),
        'limit'=>10
    ));

И то, что я вижу в дампе SQL, - это нечто вроде:

45  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 10021      1   1   167
46  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 10159      1   1   168
47  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 10021      1   1   170
48  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 10159      1   1   168
49  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 1338       1   1   169
50  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 10159      1   1   187
51  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 569        1   1   211
52  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 569        1   1   168
53  SELECT `Artist`.`name`, `Artist`.`slug` FROM `artists` AS `Artist` WHERE `Artist`.`id` = 10451      1   1   182
54  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 901         1   1   170
55  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 901         1   1   171
56  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 901         1   1   180 
57  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 900         1   1   171
58  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 900         1   1   183
59  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 901         1   1   171
60  SELECT `Releasetype`.`type` FROM `releasetypes` AS `Releasetype` WHERE `Releasetype`.`id` = 901 

(Это просто отрывок для иллюстративных целей, там гораздо больше запросов.)

Даже если каждый из этих запросов занимает всего <200 мс, все же кажется, что они могут добавить что-то существенное, и этоособенно раздражает, когда так много запросов являются дубликатами - например, все типы Releasetype.types либо 900, либо 901. </p>

Можно ли как-то реорганизовать мой запрос, мои отношения модели или что-то еще, чтобы данныеизвлекается при значительно меньшем количестве вызовов?

Ответы [ 2 ]

0 голосов
/ 06 июля 2011

Cake выполняет один основной запрос. В этом случае выполняется поиск модели «Release», и для каждой найденной там строки выполняется запрос, чтобы получить данные, которые вы указали в «Содержать».

Это ожидаемое поведение.

Большая проблема, которую я вижу, это ваше утверждение «эти запросы занимают всего <200 мс». Imo они не должны принимать более 1 мс или даже 0 мс. Казалось бы, вам нужно правильно проиндексировать эту таблицу. </p>

Мне не особенно нравится заставлять торт делать объединения, как если бы он был предназначен для объединения, разработчики тортов заставили бы его присоединиться.

Если вы действительно хотите уменьшить количество запросов, даже если они не нужны, посмотрите на a) связываемое поведение b) bindModel c) adhoc-joins

0 голосов
/ 06 июля 2011

В качестве альтернативы вы можете перестроить запрос примерно так:

$releaseList = $this->Release->find('list', array(
     'conditions' => array(
        'release_date > ' => date('Ymd'), 
        'Release.is_deleted' => false
     ),
     'fields' => array('id','id')

));
$releaseIds = array_keys($releaseList);

//now the actual query you used, searching by ids should execute faster
$forthcomingReleases = $this->Release->find('all', array(
   'conditions' => array('Release.id' => $releaseIds),
   'contain'    => array('Artist.name', 'Artist.slug', 'Releasetype.type', 'Format.Mediatype.name'),
    'order'     => array('release_date DESC'),
    'limit'     => 10 
));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...