3

我在 CakePHP 2.7.1 中使用 Sqlserver 数据源的应用程序有问题。

当我find对任何表进行操作时,响应时间非常慢(超过 1 分钟)。

我用 XDebug + QCachegrind 做了研究,我发现问题是Sqlserver->listSources(),它列出了数据库上的所有 1385 个表。

这是缩短的代码(核心文件 lib\Cake\Model\Datasource\Database\Sqlserver.php:172)

public function listSources($data = null) {
    $result = $this->_execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
    while ($line = $result->fetch(PDO::FETCH_NUM)) {
        $tables[] = $line[0];
    }
    return $tables;
}

我在块周围放置了一个简单的microtime基准测试while,几乎所有的处理时间都被这 3 行占用。

有什么办法可以加快这个速度吗?

有没有办法告诉 CakePHP 不要做这个listSources过程?

4

2 回答 2

5

打开

./Lib/Cake/Model/Datasource/Database/Sqlserver.php

查找此文本

PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL

改成

PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY

当我在我的 cakephp 中尝试时,mssql 速度提高了 50% 甚至 100%

于 2017-05-03T04:08:28.350 回答
0

这是缩短的代码

缩短的代码更相关:

public function listSources($data = null) {
    $cache = parent::listSources();
    if ($cache !== null) { 
        return $cache; # <-
    }
    $result = $this->_execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
    if (!$result) {
        $result->closeCursor();
        return array();
    }
    $tables = array();
    while ($line = $result->fetch(PDO::FETCH_NUM)) {
        $tables[] = $line[0];
    }
    $result->closeCursor();
    parent::listSources($tables); # <-
    return $tables;
}

父方法仅填充缓存(在_cake_model_缓存配置中),生产模式下的默认缓存时间为999 天,开发中为 10 秒。鉴于您当前处于开发模式的描述 - 认识到(虽然很不方便)它基本上是一个开发环境问题。

有几种解决方案,但目前最简单的方法是将数据缓存更长时间,而与调试/生产模式无关。为此,只需更改相关的缓存配置

Cache::config('_cake_model_', array(
    ...
    'duration' => '+999 days' # <-
));

如果有架构更改,您需要记住清除缓存,否则您的应用程序将不知道它。

更具侵入性的解决方案(覆盖模型schemasetSource,硬编码模型模式,因此应用程序不必查询数据库即可知道)将listSources完全删除对的调用;但是您需要管理您的模型模式给您带来极大的不便/成本 - 如果这种延迟是一个问题,那么值得追求,而不是如果不是。

于 2015-09-14T08:36:22.970 回答