CakePHP неэффективные запросы к базе данных: их можно избежать? - PullRequest
4 голосов
/ 08 октября 2009

Структура моей таблицы:

boxes (id, boxname)
boxes_items (id, box_id, item_id)

Я просматривал журналы SQL для действия "удалить ящик", и я немного испуган.

SELECT COUNT(*) AS count FROM boxes Box WHERE Box.id = 191
SELECT BoxesItem.id FROM boxes_items BoxesItem WHERE BoxesItem.box_id = 191
SELECT COUNT(*) AS count FROM boxes_items BoxesItem WHERE BoxesItem.id = 1685
DELETE FROM boxes_items WHERE boxes_items.id = 1685
SELECT COUNT(*) AS count FROM boxes_items BoxesItem WHERE BoxesItem.id = 1686
DELETE FROM boxes_items WHERE boxes_items.id = 1686

    -- snip 50 more SELECT & DELETE statements --

SELECT COUNT(*) AS count FROM boxes_items BoxesItem WHERE BoxesItem.id = 1733
DELETE FROM boxes_items WHERE boxes_items.id = 1733

DELETE FROM boxes WHERE boxes.id = 191

Это, пожалуй, наименее эффективный способ удаления из этих таблиц, который я мог придумать. Я имею в виду, это можно заменить на это:

DELETE FROM boxes WHERE id = 191
DELETE FROM boxes_items WHERE box_id = 191

Есть ли причина, по которой Кейк так поступает? Если нет, знаете ли вы какой-нибудь способ, которым я могу упростить процедуру, не нарушая основные библиотеки?


Вот соответствующие биты кода:

// app/controllers/boxes_controller.php    /////////////

public function delete($id = null) {
    if ($this->Box->del($id)) {
        $this->redirect(array('action'=>'index'));
    }
}

// app/models/box.php    ///////////////////////////////

class Boxes extends AppModel {
    var $hasAndBelongsToMany = array(
        'Item'
    );
}

// app/models/app_model.php    /////////////////////////

class AppModel {
    var $actsAs = array('Containable');
    var $recursive = -1;
}

Ответы [ 2 ]

3 голосов
/ 10 октября 2009

Если у вас есть отношение hasMany, которое, как я полагаю, является случаем, вы можете попытаться установить флаг «эксклюзивный»:

http://book.cakephp.org/view/82/hasMany

exclusive: если для параметра exclusive установлено значение true, рекурсивное удаление модели выполняется с помощью вызова deleteAll () вместо удаления каждого объекта отдельно. Это значительно повышает производительность, но не может быть идеальным для всех обстоятельств.

2 голосов
/ 08 октября 2009

К сожалению, именно так Cake делает это.

Вы можете переопределить метод del() в вашей модели с помощью чего-то вроде этого грубого макета:

function del($id, $cascade = true) {
    if ($cascade) {
        $this->BoxesItem->deleteAll(array('BoxesItem.box_id' => $id));
    }
    return parent::del($id, false);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...