【问题标题】:optimizing code / DB for a 50,000 row table为 50,000 行表优化代码/数据库
【发布时间】:2012-09-11 09:05:55
【问题描述】:

我有一个存储在数据库中的 300 条新闻文章的 RSS 提要列表,每隔几分钟我就会抓取每个提要的内容。每个提要包含大约 10 篇文章,我想将每篇文章存储在数据库中。

问题:我的数据库表超过 50,000 行并且增长迅速;每次我运行脚本以获取新提要时,它都会添加至少 100 多行。到了我的数据库达到 100% CPU 利用率的地步。

问题:如何优化我的代码/数据库?

注意:我不关心服务器的 CPU(运行时小于 15%)。我非常关心我的数据库的 CPU。

我看到的可能解决方案:

  • 目前,每次脚本运行时,它都会转到 $this->set_content_source_cache 并从表中的所有行返回一个数组数组(“链接”、“链接”、“链接”等)。这用于以后的交叉引用,以确保没有重复的链接。不会这样做并简单地更改数据库以便链接列是独特的加快速度吗?可能将这个数组扔到 memcached 中,所以它必须每小时/每天只创建一次这个数组?
  • 如果设置了链接以使其移至下一个源,则中断语句?
  • 只检查不到一周的链接?

这就是我正在做的事情:

//$this->set_content_source_cache goes through all 50,000 rows and adds each link to an array so that it's array('link', 'link', 'link', etc.)
    $cache_source_array = $this->set_content_source_cache();

    $qry = "select source, source_id, source_name, geography_id, industry_id from content_source";
    foreach($this->sql->result($qry) as $row_source) {

        $feed = simplexml_load_file($row_source['source']);

        if(!empty($feed)) {

            for ($i=0; $i < 10 ; $i++) { 
                // most often there are only 10 feeds per rss.  Since we check every 2 minutes, if there are 
                    // a few more, then meh, we probably got it last time around
                if(!empty($feed->channel->item[$i])) {
                    // make sure that the item is not blank
                    $title = $feed->channel->item[$i]->title;
                    $content = $feed->channel->item[$i]->description;
                    $link = $feed->channel->item[$i]->link;
                    $pubdate = $feed->channel->item[$i]->pubdate;
                    $source_id = $row_source['source_id'];
                    $source_name = $row_source['source_name'];
                    $geography_id = $row_source['geography_id'];
                    $industry_id = $row_source['industry_id'];

                    // random stuff in here to each link / article to make it data-worthy
                    if(!isset($cache_source_array[$link])) {

                        // start the transaction
                        $this->db->trans_start();

                        $qry = "insert into content (headline, content, link, article_date, status, source_id, source_name, ".
                            "industry_id, geography_id) VALUES ".
                            "(?, ?, ?, ?, 2, ?, ?, ?, ?)";
                        $this->db->query($qry, array($title, $content, $link, $pubdate, $source_id, $source_name, $industry_id, $geography_id));

                        // this is my framework's version of mysqli_insert_id()
                        $content_id = $this->db->insert_id();

                        $qry = "insert into content_ratings (content_id, comment_count, company_count, contact_count, report_count, read_count) VALUES ".
                            "($content_id, '0', '0', 0, '0', '0')";
                        $result2 = $this->db->query($qry);

                        $this->db->trans_complete();

                        if($this->db->trans_status() == TRUE) {
                            $cache_source_array[$link] = $content_id;
                            echo "Good!<br />";
                        } else {
                            echo "Bad!<br />";
                        }
                    } else {
                        // link alread exists
                        echo "link exists!";
                    }
                }
            }
        } else {
            // feed is empty
        }
    }
}

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    我想你回答了你自己的问题:

    目前,每次脚本运行时,它都会转到 $this->set_content_source_cache 它返回一个数组 array('link', 'link', 'link', etc.) 来自表中的所有行。 这用于以后的交叉引用以确保没有 重复链接。不会这样做,只是简单地更改数据库 链接栏是独一无二的加速器吗?

    是的,创建主键或唯一索引并允许数据库在存在重复项时抛出错误是一种更好的做法,并且应该更有效。

    参考编辑:

    mysql 5.0 indexes - Unique vs Non Unique

    http://dev.mysql.com/doc/refman/5.0/en/create-index.html

    【讨论】:

    • 我被告知,通过将列创建为唯一列,数据库首先查询自身以查看是否有任何匹配项......所以,从本质上讲,我将为每个插入执行 50,000 条记录查询.这是假的吗?你能列出一个参考吗?我通常很好奇你是否正确,所以这就是我问的原因。
    • 哇,我被教导的方式截然不同。不管教我什么新东西,我都会给你一个点(谢谢!),我会去进行一些速度测试。如果我发现它大大加快了速度,那么我一定会标记为正确的!
    • 所以,它肯定会降低 CPU Util。但我现在有一个新问题:我一次与服务器的连接太多。我相信正在发生的事情是脚本的速度比给定查询快 40 倍左右。从字面上填满了与我的数据库的所有可能连接。我的解决方案是在每次查询 10 毫秒之前在脚本中启动延迟。
    • @ICouldBeWrong 在你做任何事情之前发布一个新问题
    猜你喜欢
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多