2014-02-05 77 views
0

我想了解为什么这个查询是非常慢的一个非常大的数据库(40M +行)。 该问题似乎与“WHERE users_fb_table。installed = 1”子句。子查询(和加入查询)不使用索引与MySQL(MyISAM)

SELECT users_fb_table.`id_user_fb`, `id_fb`, `first_name` 
FROM (
    SELECT `id_user`, `id_user_fb` 
    FROM friends_table 
    WHERE friends_table.`id_user` = 10 
) AS temp 
JOIN users_fb_table ON temp.`id_user_fb` = users_fb_table.`id_user_fb` 
WHERE users_fb_table.`installed` = 1 

我已经试过不使用子查询,但结果是一样的。下面的查询返回相同的结果集(30行),并且执行时间是完全一样的:

SELECT friends_table.`id_user_fb`, `id_fb`, `first_name` 
FROM friends_table 
JOIN users_fb_table ON friends_table.`id_user_fb` = users_fb_table.`id_user_fb` 
WHERE friends_table.`id_user` = 10 and users_fb_table.`installed` = 1 

下面的查询是不是非常快:

SELECT friends_table.`id_user_fb`, `id_fb`, `first_name` 
FROM friends_table 
JOIN users_fb_table ON friends_table.`id_user_fb` = users_fb_table.`id_user_fb` 
WHERE friends_table.`id_user` = 10 limit 30 

这一次也非常快:

SELECT`id_user_fb`, `id_fb`, `first_name` 
FROM users_fb_table 
WHERE users_fb_table.`installed` = 1 limit 30 

的创建statemens两个表:

CREATE TABLE IF NOT EXISTS `users_fb_table` (
    `id_user_fb` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `id_fb` bigint(20) NOT NULL, 
    `first_name` varchar(128) NOT NULL, 
    `last_name` varchar(128) NOT NULL, 
    `full_name` varchar(128) NOT NULL, 
    `username` varchar(128) NOT NULL, 
    `gender` char(30) NOT NULL, 
    `birthday` char(128) NOT NULL, 
    `locale` char(64) NOT NULL, 
    `installed` tinyint(1) NOT NULL, 
    `email` char(128) NOT NULL, 
    `location` varchar(128) NOT NULL, 
    PRIMARY KEY (`id_user_fb`), 
    UNIQUE KEY `id_fb` (`id_fb`), 
    KEY `installed` (`installed`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

CREATE TABLE IF NOT EXISTS `friends_table` (
    `id_friend` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `id_user` bigint(20) unsigned NOT NULL, 
    `id_user_fb` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`id_friend`), 
    UNIQUE KEY `id_index` (`id_user`,`id_user_fb`), 
    KEY `id_user` (`id_user`), 
    KEY `id_user_fb` (`id_user_fb`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

我能做些什么来使执行速度更快? 我试图创建一个索引但没有成功的子查询。

谢谢您的帮助。

+0

无论安装标志如何,您对每个用户有多少条记录?你可以数量“慢”和“快”? –

+0

它取决于用户,它可以变化为100到数千。我已经在低负载情况下测试了这个查询,并且一个慢查询需要0.03秒(可能不会太多,但是在高负载时可能需要几秒钟)。虽然快速我的意思是0.0002秒。 – Francesco

回答

0

您的查询不具可比性。运行“快速”的最后两个使用limit子句。你的查询没有。尝试将limit 30添加到您的查询中,以查看它是否运行得更快。它可能不会,因为查询可能需要经过30多条记录才能找到满足安装条件的30条记录。

使用limit表明每个用户在fb表中匹配的行数很多。如果是这样,请尝试以下索引:users_fb_table(id_user_fb, installed)。此索引可用于joinwhere条件。

其实,一个更好的索引是users_fb_table(id_user_fb, installed, id_fb, first_name)。该查询“覆盖”了查询,因此执行引擎只能使用索引满足查询,而不必引用数据页面。

+0

事实上,第一次查询的限制30是需要同一时间的,下限使得它更快。我会尝试添加您建议的索引。 – Francesco