【问题标题】:Ajax request takes too long to complete when working with large database处理大型数据库时,Ajax 请求需要很长时间才能完成
【发布时间】:2015-12-14 02:10:43
【问题描述】:

我正在开发一个用 Yii 框架(版本 1.1.14)编写的网站,该网站允许上传和显示新闻。网站管理员可以选择三个新闻推广到主页并指定它们的显示顺序。我正在使用 Mysql 数据库。 news 表有两个字段:isChecked(0 或 1)和 homepagePos(整数)以及其他字段。 isChecked 字段决定是否选择新闻在首页显示,homepagePos 字段决定新闻显示的顺序。我使用 jquery 的可排序插件对新闻进行排序。当用户选择要显示的新闻并点击保存按钮时,新闻 id 会通过 ajax 发送到 php。

将值发送到新闻控制器的javascript部分如下:

$(document).on('click', '#saveToHomepage', function() 
{
    var url = ajaxRequestSendUrl;   //ajaxRequestSendUrl contains url to news controller's promote to homepage method.
    $.ajax({
        method: "GET",
        url: url,
        data: {
            contentIds: contentIds, //contentIds contains an array of news Ids in certain order
            },
        success: function() {
        // Show success message
        },
        error: function() {
            alert('Some error occured. Please reload the page and try again.');
        }
    });
});

这是新闻控制器中提升到主页的方法:

public function actionHomepage()
{
    $allNews = News::model()->findAll();
    $value = $_GET['contentIds'];
    foreach ($allNews as $news) {
        if($news->id == $value[0] ||$news->id == $value[1] ||$news->id == $value[2])
        {
            $news->isChecked = 1;
            $news->homepagePos = array_search($news->id, $value); //Assign index of the array as the position
            $news->save();
        }
        else
        {
            $news->isChecked = 0;
            $news->homepagePos = -1;
            $news->save();
        }
    }
}

我的问题是我拥有的新闻表有超过 2k 的数据。因此,ajax 调用需要很长时间(超过一分钟)才能完成。有什么方法可以优化代码,还是有其他方法可以减少完成此操作所需的时间? 在此先感谢

【问题讨论】:

  • 你试过使用分页吗?
  • @jimmypage 你为什么不使用你拥有的 id 查询模型而不是获取整个 News 模型?
  • 为什么要保存在 fetch 中?
  • 这需要很长时间,因为您必须获取整个表,在模型中进行更改,然后通过模型更新每一行。您为什么不使用两个查询来执行此操作:第一个将整个表设置为未检查状态,第二个仅在具有所选 id 的行中设置检查状态?
  • 不要获取所有新闻,因为这可能需要很长时间,具体取决于有多少新闻条目。相反,您可以预先重置 isCheckedhomepagePos 字段,然后使用您获得的 ID 查询表,然后设置字段。

标签: php jquery mysql ajax yii


【解决方案1】:

三个查询:第一个将整个表设置为未选中状态,其余的仅在每个选定id的行中设置选中状态

public function actionHomepage()
{
    $values = $_GET['contentIds'];
    $sql = "UPDATE news SET idChecked=0,homepagePos = -1";
    Yii::app()->db
        ->createCommand($sql)
        ->execute();
    for($ii = 0; $ii < 3; $ii++) {
        $sql = "UPDATE news SET idChecked = 1,homepagePos = ':homepagePos' WHERE id=:id";
        Yii::app()->db
            ->createCommand($sql)
            ->bindValues(array(':homepagePos' => array_search($ii, $values), ':id' => $values[$ii]))
            ->execute();
    }
}

【讨论】:

  • 谢谢。我对此做了一些小改动,现在它可以工作了......正如预期的那样更快!
【解决方案2】:

我不确定,但是为什么不通过发送所选新闻的 id 从数据库本身获取过滤后的记录。我不知道你的后端语言。似乎,您正在获取所有记录并应用过滤。这会消耗时间。而是从数据库中获取过滤后的新闻。

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    这需要很长时间,因为您要获取所有记录,然后更新这三个 id。你可以试试这个:

    $criteria = new CDbCriteria;
    $criteria->addInCondition( "id" , $value ) ; // $value = array ( 1, 2, 3 );
    News::model()->updateAll(array('isChecked'=>'1','homepagePos'=>'val2'), $criteria);
    

    您可以事先进行更新以重置所有 homepagePos,然后仅更新您需要的 ID。

    【讨论】: