针对大数据优化MySQL交叉查询

时间:2017-07-17 10:20:28

标签: mysql optimization reporting bigdata

这是我的表结构:

CREATE TABLE `instagram_user_followers_mapping` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`instagram_user_id` varchar(20) NOT NULL,
`instagram_profile_id` varchar(20) NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `instagram_unique_user_follower_mapping` (`instagram_user_id`,`instagram_profile_id`),
KEY `instagram_user_followers_mapping_created_at_index` (`created_at`),
KEY `instagram_user_followers_mapping_updated_at_index` (`updated_at`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED

我在这张表中有超过1亿行。当我尝试在两个或多个" instagram_user_id"之间获取常用关注者时,它适用于表中少于20,000行的配置文件。但对于行超过2mil的配置文件,它的工作速度非常慢。我想让这些数据实时显示,以便进行分析和报告。最终用户可能会选择任何配置文件组合,因此在此处创建摘要表并不是一个很好的选择。

我用来获取交集的查询是:

select instagram_profile_id, count(*) as myCount 
from instagram_user_followers_mapping 
where instagram_user_id IN ('1142282','346115','663620','985530') 
group by instagram_profile_id HAVING myCount >= 4

3 个答案:

答案 0 :(得分:0)

IN条款有点特别。使用此查询可以解决您的问题。我在{where>子句中将count(*)更改为count(id)并将IN语句更改为相等。

select instagram_profile_id, count(id) as myCount 
from instagram_user_followers_mapping 
where instagram_user_id = '1142282' or instagram_user_id = '346115' or instagram_user_id = '663620' or instagram_user_id = '985530'
group by instagram_profile_id HAVING myCount >= 4

答案 1 :(得分:0)

' IN' vs' OR'应该不是问题。查询解释器应该认为它们是相同的(EXPLAIN应该证明这一点)。

实际上,在该查询上复制和粘贴EXPLAIN非常有用......

由于这是我们在这里处理的相当多的行,因为你的索引看起来足够,我会看(2)事情。首先是整体db配置(确保足够的ram到innodb_buffer_pool等)。第二个(也是更可能的)问题是GROUP BY非常慢。尝试增加排序缓冲区类型参数,并在这里查看更多想法: https://dev.mysql.com/doc/refman/5.7/en/group-by-optimization.html https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html

另外,如果可以,请尝试运行每个' WHERE instagram_user_id ='作为单独的查询。

一般来说,这不是MySQL快速恶作剧的事情,但通过一些工作,你可以让它为你工作。您可能需要在应用程序方面获得一些创意,具体取决于您需要多快的速度。

答案 2 :(得分:0)

这应该运行得更快,但需要构建查询:

select  instagram_profile_id
    from  instagram_user_followers_mapping AS t
    WHERE  instagram_user_id = '1142282'
      AND  EXISTS
        (
        SELECT  *
            FROM  instagram_user_followers_mapping
            WHERE  instagram_profile_id = t.instagram_profile_id
              AND  instagram_user_id = '346115' 
        )
      AND  EXISTS 
        (
        SELECT  *
            FROM  instagram_user_followers_mapping
            WHERE  instagram_profile_id = t.instagram_profile_id
              AND  instagram_user_id = '663620' 
        )
      AND  EXISTS 
        (
        SELECT  *
            FROM  instagram_user_followers_mapping
            WHERE  instagram_profile_id = t.instagram_profile_id
              AND  instagram_user_id = '985530' 
        );

此公式避免了文件排序,并避免收集给定profile_id的所有user_id(反之亦然)。

innodb_buffer_pool_size是否大于索引大小?