1

私はデータベースに保存されているニュース記事の300のRSSフィードのリストを持っており、数分ごとにすべてのフィードのコンテンツを取得します。各フィードには約10個の記事が含まれており、各記事をDBに保存したいと思います。

問題:私のDBテーブルは50,000行を超えており、急速に増加しています。スクリプトを実行して新しいフィードを取得するたびに、少なくとも100行が追加されます。それは私のDBが100%のCPU使用率に達しているところまでです。

質問:コード/ DBを最適化するにはどうすればよいですか?

注:サーバーのCPUは気にしません(これを実行すると15%未満になります)。私は自分のDBのCPUを大いに気にかけています。

私が見ている可能な解決策:

  • 現在、スクリプトが実行されるたびに、スクリプトは$ this-> set_content_source_cacheに移動し、テーブル内のすべての行から配列('link'、'link'、'link'など)の配列を返します。これは、後で相互参照して、重複するリンクがないことを確認するために使用されます。これを実行してDBを変更するだけで、リンク列が一意になるようにすると、処理が高速化されますか?おそらく、代わりにこの配列をmemcachedにスローするので、この配列を1時間に1回だけ作成する必要がありますか?
  • リンクが次のソースに移動するように設定されている場合は、breakステートメント?
  • 1週間未満のリンクのみをチェックしますか?

これが私がしていることです:

//$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
        }
    }
}
4

1 に答える 1

1

私はあなたがあなた自身の質問に答えたと思います:

現在、スクリプトが実行されるたびに、スクリプトは$ this-> set_content_source_cacheに移動し、テーブル内のすべての行から配列('link'、'link'、'link'など)の配列を返します。これは、後で相互参照して、重複するリンクがないことを確認するために使用されます。これを実行してDBを変更するだけで、リンク列が一意になるようにすると、処理が高速化されますか?

はい。主キーまたは一意のインデックスを作成し、重複がある場合にDBがエラーをスローできるようにすることは、はるかに優れた方法であり、はるかに効率的です。

参照編集:

mysql5.0インデックス-一意と非一意

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

于 2012-09-19T03:55:19.177 に答える