我的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天。
我的问题是 - 我必须在这里遗漏一些东西。也许有更高效的查询可能,或者我应该改变一些数据库结构?任何帮助将不胜感激:)
答案 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)
第一步是将索引添加到经常用作搜索条件的列。