【问题标题】:CakePHP inefficient database queries: can they be avoided?CakePHP 低效的数据库查询:可以避免吗?
【发布时间】:2009-10-07 22:58:22
【问题描述】:

我的表结构:

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

Cake 这样做有什么理由吗?如果没有,您知道我可以在不破坏核心库的情况下简化程序吗?


以下是相关的代码:

// 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;
}

【问题讨论】:

  • 我假设您使用的是 ORM 形式?
  • 如果是,CakePHP 是否公开了您可以自己使用的数据库库?
  • 是的,Cake 有自己的(?)ORM 系统,但我相信这些语句是在更高级别生成的——也就是说,Cake 代码告诉 DBO 生成大约 50 个命令.这有意义吗?
  • 您可以发布您的操作中的实际代码以及任何相关的回调吗?也许你有一些可以修剪的东西?

标签: php sql cakephp


【解决方案1】:

如果您有 hasMany 关系,我假设您可能想尝试设置“独占”标志:

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

exclusive:当 Exclusive 设置为 true 时,递归模型删除通过 deleteAll() 调用进行删除,而不是单独删除每个实体。这大大提高了性能,但可能并不适合所有情况。

【讨论】:

    【解决方案2】:

    不幸的是,Cake 就是这样做的。

    您可以使用以下粗略模型覆盖模型中的 del() 方法:

    function del($id, $cascade = true) {
        if ($cascade) {
            $this->BoxesItem->deleteAll(array('BoxesItem.box_id' => $id));
        }
        return parent::del($id, false);
    }
    

    【讨论】:

    • 方法结束时对 parent::del(...) 的调用。它到底是做什么的?
    • @smchacko:它调用父类的原始del() 方法、模型继承自的类以及覆盖它的del()。了解对象继承:php.net/manual/en/language.oop5.inheritance.phpparent 关键字:php.net/keyword.parent
    • 如果您想避免它生成的低效 SQL 查询,为什么还要再次调用 parent::del()?
    • 父级会发现自己没有要删除的Item,所以不会一一调用所有的delete语句。
    • 更准确地说,我们调用它时将$cascade 设置为false,因此它甚至不会打扰关联的模型,只需对主模型执行一次删除。看到马修的回答,我实际上会选择他的。如果您想对删除操作进行大量控制,我的方法仍然很有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    相关资源
    最近更新 更多