代码之家  ›  专栏  ›  技术社区  ›  Fragsworth

原则查询内存使用情况

  •  10
  • Fragsworth  · 技术社区  · 17 年前

    Doctrine似乎需要超过4MB的RAM来执行一个简单的查询:

    print memory_get_peak_usage()." <br>\n";
    $q = Doctrine_Query::create()
        ->from('Directories d')
        ->where('d.DIRECTORY_ID = ?', 5);
    
    $dir = $q->fetchOne();
    print $dir['name']." ".$dir['description']."<br>\n";
    
    print memory_get_peak_usage()." <br>\n";
    
    /***************  OUTPUT:  **************************
    
    6393616
    testname testdescription
    10999648
    
    /***************************************************/
    

    这是在一个数据很少的测试数据库上——我查询的项目除了这里显示的数据外,不包含任何其他数据。

    7 回复  |  直到 15 年前
        1
  •  6
  •   Tapper Pascal MARTIN    14 年前

    据我所知,你的代码似乎没有错。..


    作为测试,我用一个非常简单的表设置了一个快速示例 (仅四个字段) .

    var_dump(number_format(memory_get_peak_usage()));
    
    $test = Doctrine::getTable('Test')->find(1);
    
    var_dump(number_format(memory_get_peak_usage()));
    

    这样做时,我有这样的输出:

    string '1,316,088' (length=9)
    string '2,148,760' (length=9)
    

    考虑到表格非常简单,而且我只取了一行,这对我来说似乎也“很多”——但这与你得到的结果以及我在其他项目上看到的结果非常一致:-(


    如果你只需要显示你的数据,而不需要使用它(即更新/删除/…),一个解决方案可能是不获取复杂的对象,而只获取一个简单的数组:

    $test = Doctrine::getTable('Test')->find(1, Doctrine::HYDRATE_ARRAY);
    

    string '1,316,424' (length=9)
    string '2,107,128' (length=9)
    

    只有40KB的差异——好吧,对于更大的对象/更多的行,这可能仍然是一个好主意。..


    Improving Performance


    哦,顺便说一句:我在PHP 5.3.0上做了这个测试;也许这会对使用的内存量产生影响。..

        2
  •  5
  •   Aries    16 年前

    我同意romab的回答——在使用大型libs/framework时,使用OpCode缓存是必须的。

    10.25 megabytes
    RV David
    16.5 megabytes
    

    APC结果:

    3 megabytes
    RV David
    4.25 megabytes
    

        3
  •  4
  •   romanb    16 年前

    那么,这些内存使用量是从哪里来的呢?正如Pascal MARTIN所指出的,数组水合作用并没有太大区别,这是合乎逻辑的,因为我们在这里只讨论了一些记录。

    内存消耗来自通过自动加载按需加载的所有类。

        4
  •  4
  •   snakewa    14 年前

    如果你只需要从数据库中获取一条记录,请确保:

    $q->limit(1)->fetchOne() 
    

    大桌子上的内存使用量大幅下降。

    public function fetchOne($params = array(), $hydrationMode = null)
    {
        $collection = $this->execute($params, $hydrationMode);
    
        if (is_scalar($collection)) {
            return $collection;
        }
    
        if (count($collection) === 0) {
            return false;
        }
    
        if ($collection instanceof Doctrine_Collection) {
            return $collection->getFirst();
        } else if (is_array($collection)) {
            return array_shift($collection);
        }
    
        return false;
    }
    
        5
  •  2
  •   liutis    16 年前

    Doctrine在Doctrine_Record、Doctrine_Collection和Doctrine_Query上提供了一个free()函数,该函数消除了对这些对象的循环引用,将它们释放出来进行垃圾收集。 More info..

    • $query->free()
        6
  •  1
  •   Mark E. Haase    16 年前

    • 你使用的是哪个版本的教义?
    • 你在用自动装弹机吗?

    在Doctrine 1.1中,默认的自动加载行为被称为“主动”,这意味着即使你在任何特定请求中只使用了一两个模型类,它也会加载你的所有模型类。将该行为设置为“保守”将减少内存使用。

        7
  •  0
  •   Ikon    16 年前

    sfConfig::set('sf_debug', false);