如何优化Mysql使用count(distinct)和join

时间:2012-10-31 09:34:13

标签: mysql join distinct

我有两张桌子,他们的结构如下:

CREATE TABLE  `metaservice`.`user` (
  `id` bigint(18) NOT NULL AUTO_INCREMENT,
  `userId` bigint(18) NOT NULL,
  `name` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `userId` (`userId`) USING BTREE,
  KEY `nameIndex` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

CREATE TABLE  `metaservice`.`tweet` (
  `id` bigint(18) NOT NULL AUTO_INCREMENT,
  `tweetId` bigint(18) NOT NULL,
  `reqId` int(8) NOT NULL DEFAULT '0',
  `postedTime` datetime NOT NULL,
  `body` text NOT NULL,
  `userId` bigint(18) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK69A46713BA64537` (`userId`),
  KEY `reqId` (`reqId`),
  CONSTRAINT `FK69A46713BA64537` FOREIGN KEY (`userId`) REFERENCES `user` (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

我在下面得到了这个SQL查询:

select
        count(distinct user.name) as c 
    from
        tweet as tweet 
    inner join
        user as user 
            on tweet.userId=user.userId  
            and tweet.reqId in (
                327774,
            215173,
            104302,
            239188,
            317122,
            972632,
            424187,
            644254,
            946792,
            543258)

当推文表有6W记录并且用户表有6w +记录时,它太慢了 此查询返回结果:10.45秒中的60594

4 个答案:

答案 0 :(得分:1)

我建议您按如下方式使用EXPLAIN:

EXPLAIN select
        count(distinct user.name) as c 
    from
        tweet as tweet 
    inner join
        user as user 
            on tweet.userId=user.userId  
            and tweet.reqId in (
                327774,
            215173,
            104302,
            239188,
            317122,
            972632,
            424187,
            644254,
            946792,
            543258)

然后分析EXPLAIN为您提供的响应。有关MySQL解释的更多信息可以在以下来源找到:

MySQL Explain Syntax

Optimize Queries with Explain

Using MySQL Explain

MySQL Explain Reference

一旦查看了结果,您就需要决定应该将哪些列编入索引。

答案 1 :(得分:0)

试试这个:

select count(*) as c from (
select
       user.name 
    from
        tweet as tweet 
    inner join
        user as user 
            on tweet.userId=user.userId  
            and tweet.reqId in (
                327774,
            215173,
            104302,
            239188,
            317122,
            972632,
            424187,
            644254,
            946792,
            543258)
group by user.name) a

答案 2 :(得分:0)

我建议你索引你的密钥。索引不仅适用于主键或唯一键。如果您要搜索的表中有任何列,则几乎总是将它们编入索引。

另请阅读Link

答案 3 :(得分:0)

试试这个 -

SELECT
  COUNT(DISTINCT user.name) AS c
FROM
  tweet AS tweet
INNER JOIN user AS user
  ON tweet.userId = user.userId
INNER JOIN (
    SELECT 327774 AS reqId UNION
    SELECT 215173 UNION
    SELECT 104302 UNION
    SELECT 239188 UNION
    SELECT 317122 UNION
    SELECT 972632 UNION
    SELECT 424187 UNION
    SELECT 644254 UNION
    SELECT 946792 UNION
    SELECT 543258
  ) t
  ON tweet.reqId  = t.reqId;