【问题标题】:Tree reorder slow in CakePHPCakePHP中的树重新排序很慢
【发布时间】:2015-04-17 11:51:31
【问题描述】:

我正在使用 Tree Behavior 来存储有序的项目列表。

当我向树中添加新元素时,我会调用“reorder()”函数对其进行重新排序。它非常慢。我一直在尝试很多事情。我的最后一个测试是一个包含 70 个元素(1 个父元素和 69 个子元素)的表。 reorder() 函数所用的时间是 1 分 20 秒。我正在使用 MySQL,并且在 id、parent_id、rght 和 lft 字段中有索引。

我做错了什么?

谢谢

【问题讨论】:

    标签: cakephp


    【解决方案1】:

    我也花了一些时间调查这个。

    事实证明,重新排序功能非常低效。基本上它将第一项的左右字段设置为高值,然后重新排序其余字段。然后它对第二个项目做同样的事情,等等。你最终会运行数万个查询,对于只有一百个项目的树。

    我用下面的代码整理出来。这样做只是更新每条记录一次,并保留左右值之间的差距。它递归地遍历项目并正确地重新排序。

    在 app/Model/Behavior 中创建一个名为“BRTreeBehavior.php”的新文件,然后修改模型的 $actsAs 字段以使用 BRTree 而不是 Tree。

    <?php
    /**
     * Copyright 2015, Perthweb Pty Ltd
     *
     */
    
    App::uses('TreeBehavior', 'Model/Behavior');
    
    /**
     * BetterReorderTree Behavior.
     *
     * Improves reorder of tree behavior
     *
     */
    class BRTreeBehavior extends TreeBehavior {
    
    
        /**
         * Reorder method.
         *
         * Reorders the nodes (and child nodes) of the tree according to the field and direction specified in the parameters.
         * This method does not change the parent of any node.
         *
         * Requires a valid tree, by default it verifies the tree before beginning.
         *
         * Options:
         *
         * - 'id' id of record to use as top node for reordering
         * - 'field' Which field to use in reordering defaults to displayField
         * - 'order' Direction to order either DESC or ASC (defaults to ASC)
         * - 'verify' Whether or not to verify the tree before reorder. defaults to true.
         *
         * @param Model $Model Model instance
         * @param array $options array of options to use in reordering.
         * @return boolean true on success, false on failure
         * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::reorder
         */
        public function reorder(Model $Model, $options = array()) {
            $options = array_merge(array('id' => null, 'field' => $Model->displayField, 'order' => 'ASC', 'verify' => true, 'startIndex' => null), $options);
            extract($options);
            if ($verify && !$this->verify($Model)) {
                return false;
            }
            $verify = false;
            extract($this->settings[$Model->alias]);
            $fields = array($Model->primaryKey, $field, $left, $right);
            $sort = $field . ' ' . $order;
            $nodes = $this->children($Model, $id, true, $fields, $sort, null, null, $recursive);
    
            $cacheQueries = $Model->cacheQueries;
            $Model->cacheQueries = false;
            if ($nodes) {
                if($id == null){
                    $index = 1;
                }
                else if($startIndex == null){
                    $index = $nodes[0][$Model->alias][$left];
                }
                else {
                    $index = $startIndex;
                }
    
                foreach ($nodes as $node) {
                    $id = $node[$Model->alias][$Model->primaryKey];
    
                    $difference = $node[$Model->alias][$right] - $node[$Model->alias][$left];
    
                    $nodeData = array(
                        $Model->alias => array(
                            $Model->primaryKey => $id,
                            $left => $index,
                            $right => $index + $difference
                        )
                    );
    
                    $Model->create();
                    $Model->save($nodeData, array('validate' => false, 'callbacks' => false, 'fieldList' => array($left, $right)));
                    $Model->clear();
    
                    $startIndex = $index + 1;
    
                    if ($difference != 1) {
                        $this->reorder($Model, compact('id', 'field', 'order', 'verify', 'startIndex'));
                    }
    
                    $index += $difference + 1;
                }
            }
            $Model->cacheQueries = $cacheQueries;
            return true;
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      相关资源
      最近更新 更多