如何加速MySQL数据库/查询?

时间:2011-11-20 16:49:00

标签: php mysql sql myisam

我的MySQL数据库中有两个表,用户和推文,如下所示:

TABLE users (
  uid int(7) NOT NULL AUTO_INCREMENT,
  twitter_uid int(10) NOT NULL,
  screen_name varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  tweets int(6) NOT NULL,
  followers_count int(7) NOT NULL,
  statuses_count int(7) NOT NULL,
  created_at int(10) NOT NULL,
  PRIMARY KEY (uid)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

TABLE tweets (
  tweet_id int(11) NOT NULL AUTO_INCREMENT,
  `query` varchar(5) NOT NULL,
  id_str varchar(18) NOT NULL,
  created_at int(10) NOT NULL,
  from_user_id int(11) NOT NULL,
  from_user varchar(256) NOT NULL,
  `text` text NOT NULL,
  PRIMARY KEY (tweet_id),
  KEY id_str (id_str)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

推文表包含超过200万条记录。我已将唯一用户(取自tweets.from_user)放在users表中。它现在包含94,100个用户。我现在想要计算每个用户发布的推文数量,如下所示(在PHP中):

res = db_query('SELECT uid, screen_name FROM users WHERE tweets = 0 LIMIT 150');
while ($user = db_fetch_object($result)) {
  $res2 = db_query(
    "SELECT COUNT(tweet_id) FROM tweets WHERE from_user = '%s'",
    $user->screen_name
  );
  $cnt = db_result($result2);
  db_query("UPDATE users SET tweets = %d WHERE uid = %d", $cnt, $user->uid);
}

然而,这段代码非常慢。计算150个用户的推文大约需要5分钟。按此速率,所有用户完成此任务大约需要3天。

我的问题是 - 我必须在这里遗漏一些东西。也许有更高效的查询可能,或者我应该改变一些数据库结构?任何帮助将不胜感激:)

5 个答案:

答案 0 :(得分:6)

我认为这里最糟糕的问题是有多个查询。这很可能比索引问题更糟糕。您应该尝试只有一个查询。

UPDATE users 
SET users.tweets = (SELECT COUNT(tweet_id) 
                    FROM tweets 
                    WHERE tweets.from_user = users.uid 
                    AND users.tweets =0
                   )

答案 1 :(得分:2)

您已将所有相关属性编入索引吗?特别是from_user应该有一个索引!

答案 2 :(得分:2)

我首先将所有这些内容压缩到一个UPDATE语句中:

UPDATE users
   SET tweets =
        ( SELECT COUNT(1)
            FROM tweets
           WHERE tweets.from_user = users.screen_name
        )
 WHERE users.tweets = 0
 LIMIT 150
;

然后我会看看指数。特别是,确保tweets.from_user上有索引。 (有关如何在表列上创建索引,请参阅http://dev.mysql.com/doc/refman/5.0/en/create-index.html。)

答案 3 :(得分:2)

虽然你可以通过将这些SQL语句“压缩”为一个来快速更新users.tweets(如其他答案所示),当用户发新推文时你会怎么做?如何知道users.tweets需要再次更新?

  • 一种方法是,只要从users.tweets表中删除或插入行,或者修改tweets,就会生成一个更新tweets.from_user的触发器。
  • 您也可以完全删除users.tweets,并根据需要动态统计推文。

在任何情况下,要加快SELECT COUNT(tweet_id) FROM tweets WHERE from_user = '%s'查询,您需要在{from_user}上创建索引。由于tweet_id不为NULL,COUNT(tweet_id)等同于COUNT(*) - 否则将需要{from_user,tweet_id}上的复合索引。

答案 4 :(得分:1)

第一步是将索引添加到经常用作搜索条件的列。