以下是查询:
SELECT COUNT(*) AS c, MAX(`followers_count`) AS max_fc,
MIN(`followers_count`) AS min_fc, MAX(`following_count`) AS max_fgc,
MIN(`following_count`) AS min_fgc, SUM(`followers_count`) AS fc,
SUM(`following_count`) AS fgc, MAX(`updates_count`) AS max_uc,
MIN(`updates_count`) AS min_uc, SUM(`updates_count`) AS uc
FROM `profiles`
WHERE `twitter_id` IN (SELECT `followed_by`
FROM `relations`
WHERE `twitter_id` = 123);
这两个表格为profiles
和relations
。两者都有超过1,000,000行,InnoDB引擎。两者都有twitter_id
上的索引,relations
在(twitter_id
,followed_by
)上有一个额外的索引。查询执行时间超过6秒,这真让我感到沮丧。我知道我可以以某种方式加入,但我的MySQL知识并不那么酷,这就是我要求你帮助的原因。
先谢谢大家=)
干杯, K~
更新
好吧,我设法下降到2.5秒。我使用INNER JOIN并添加了三个索引对。这是EXPLAIN的结果:
id, select_type, table, type, possible_keys,
key, key_len, ref, rows, Extra
1, 'SIMPLE', 'r', 'ref', 'relation',
'relation', '4', 'const', 252310, 'Using index'
1, 'SIMPLE', 'p', 'ref', 'PRIMARY,twiter_id,id_fc,id_fgc,id_uc',
'id_uc', '4', 'follerme.r.followed_by', 1, ''
希望这有帮助。
另一次更新
以下是两个表的SHOW CREATE TABLE语句:
CREATE TABLE `profiles` (
`twitter_id` int(10) unsigned NOT NULL,
`screen_name` varchar(45) NOT NULL default '',
`followers_count` int(10) unsigned default NULL,
`following_count` int(10) unsigned default NULL,
`updates_count` int(10) unsigned default NULL,
`location` varchar(45) default NULL,
`bio` varchar(160) default NULL,
`url` varchar(255) default NULL,
`image` varchar(255) default NULL,
`registered` int(10) unsigned default NULL,
`timestamp` int(10) unsigned default NULL,
`relations_timestamp` int(10) unsigned default NULL,
PRIMARY KEY USING BTREE (`twitter_id`,`screen_name`),
KEY `twiter_id` (`twitter_id`),
KEY `screen_name` USING BTREE (`screen_name`,`twitter_id`),
KEY `id_fc` (`twitter_id`,`followers_count`),
KEY `id_fgc` (`twitter_id`,`following_count`),
KEY `id_uc` (`twitter_id`,`updates_count`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `relations` (
`id` int(10) unsigned NOT NULL auto_increment,
`twitter_id` int(10) unsigned NOT NULL default '0',
`followed_by` int(10) unsigned default NULL,
`timestamp` int(10) unsigned default NULL,
PRIMARY KEY USING BTREE (`id`,`twitter_id`),
UNIQUE KEY `relation` (`twitter_id`,`followed_by`)
) ENGINE=InnoDB AUTO_INCREMENT=1209557 DEFAULT CHARSET=utf8
哇,多么糟糕=)抱歉!
答案 0 :(得分:3)
联接看起来像这样:
SELECT COUNT(*) AS c,
MAX(p.`followers_count`) AS max_fc,
MIN(p.`followers_count`) AS min_fc,
MAX(p.`following_count`) AS max_fgc,
MIN(p.`following_count`) AS min_fgc,
SUM(p.`followers_count`) AS fc,
SUM(p.`following_count`) AS fgc,
MAX(p.`updates_count`) AS max_uc,
MIN(p.`updates_count`) AS min_uc,
SUM(p.`updates_count`) AS uc
FROM `profiles` AS p
INNER JOIN `relations` AS r ON p.`twitter_id` = r.`followed_by`
WHERE r.`twitter_id` = 123;
为了帮助优化它,您应该在两个查询上运行EXPLAIN SELECT ....
答案 1 :(得分:1)
SELECT COUNT(*) AS c,
MAX(`followers_count`) AS max_fc, MIN(`followers_count`) AS min_fc,
MAX(`following_count`) AS max_fgc, MIN(`following_count`) AS min_fgc,
SUM(`followers_count`) AS fc, SUM(`following_count`) AS fgc,
MAX(`updates_count`) AS max_uc, MIN(`updates_count`) AS min_uc, SUM(`updates_count`) AS uc
FROM `profiles`
JOIN `relations`
ON (profiles.twitter_id = relations.followed_by)
WHERE relations.twitted_id = 123;
可能会快一点,但你需要测量并检查是否确实如此。
答案 2 :(得分:1)
创建以下复合索引:
profiles (twitter_id, followers_count)
profiles (twitter_id, following_count)
profiles (twitter_id, updates_count)
并为了上帝的缘故发布查询计划。
顺便说一下,COUNT(*)
返回了多少行?
<强>更新强>
你的桌子行很长。在您选择的所有字段上创建复合索引:
profiles (twitter_id, followers_count, following_count, updates_count)
以便JOIN
查询可以从该索引中检索所需的所有值。
答案 3 :(得分:1)
count(*)在InnoDB引擎下是一项非常昂贵的操作,你是否尝试过没有那块的查询?如果它导致处理时间最长,那么也许你可以保持一个运行值而不是每次查询它。
答案 4 :(得分:1)
我从程序员的角度来解决这个问题;我有一个单独的表(或某处的存储区域)存储与原始查询中的每个字段关联的max,min和sum值,并在每次更新和添加表记录时更新这些值。 (尽管如果处理不当,删除可能会有问题)。
在填充这些值的原始查询完成后(这与您发布的查询几乎相同),您实际上是在减少最终查询以从数据表中获取一行,而不是计算所有内容一次。