如何在社交表结构中优化这个mysql查询?

时间:2017-02-28 09:42:30

标签: mysql sql query-optimization

方案

CREATE TABLE IF NOT EXISTS `content` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `entity_uid` int(11) NOT NULL,
   ....
  PRIMARY KEY (`uid`),
  UNIQUE KEY `insert_at` (`insert_at`),
  KEY `fk_entity` (`entity_uid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `entity` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `entity_comment` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `entity_uid` int(11) NOT NULL,
  `user_uid` int(11) NOT NULL,
   ....
  PRIMARY KEY (`uid`),
  KEY `fk_entity` (`entity_uid`),
  KEY `fk_user` (`user_uid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `entity_like` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `entity_uid` int(11) NOT NULL,
  `user_uid` int(11) NOT NULL,
  ....
  PRIMARY KEY (`uid`),
  KEY `fk_entity` (`entity_uid`),
  KEY `fk_user` (`user_uid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `entity_share` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `entity_uid` int(11) NOT NULL,
  `user_uid` int(11) NOT NULL,
  `share_type` int(2) NOT NULL,
  ....
  PRIMARY KEY (`uid`),
  KEY `fk_entity` (`entity_uid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `entity_view` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `entity_uid` int(11) NOT NULL,
  `user_uid` int(11) NOT NULL,
   ....
  PRIMARY KEY (`uid`),
  KEY `fk_entity` (`entity_uid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(30) NOT NULL,
  ....
  PRIMARY KEY (`uid`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

查询1 - 使用Left Join [查询耗时16.3032秒]

SELECT c . * , COUNT(DISTINCT ev.uid) AS view_count, COUNT( DISTINCT el.uid ) AS like_count, COUNT( DISTINCT ec.uid ) AS reply_count, COUNT( DISTINCT es.uid ) AS share_count
FROM content AS c
LEFT JOIN entity_view AS ev ON ev.entity_uid = c.entity_uid
LEFT JOIN entity_like AS el ON el.entity_uid = c.entity_uid
LEFT JOIN entity_share AS es ON es.entity_uid = c.entity_uid
LEFT JOIN entity_comment AS ec ON ec.entity_uid = c.entity_uid
GROUP BY c.uid

编辑 - 解释

enter image description here

查询2 - 使用Sub query [查询耗时0.0069秒]

SELECT c.*,
    (SELECT COUNT(*) FROM entity_view WHERE entity_uid = c.entity_uid) AS view_count ,
    (SELECT COUNT(*) FROM entity_like WHERE entity_uid = c.entity_uid) AS like_count ,
    (SELECT COUNT(*) FROM entity_comment WHERE entity_uid = c.entity_uid) AS reply_count ,
    (SELECT COUNT(*) FROM entity_share WHERE entity_uid = c.entity_uid) AS share_count
FROM content AS c

编辑 - 解释

enter image description here

结果

uid | data of content | view_count | like_count | reply_count | share_count |
-----------------------------------------------------------------------------
1   | .....           | 100        | 10         | 5           | 6           |
-----------------------------------------------------------------------------
2   | .....           | 200        | 20         | 20          | 3           |
-----------------------------------------------------------------------------
3   | .....           | 300        | 10         | 10          | 2           |
-----------------------------------------------------------------------------

解释

  • 存储引擎:InnoDB
  • entity_ {action}:当用户{action}发生时插入。当(例如)entity_view插入时,用户会看到内容。

问题

  

如何在上面的mysql查询中进行更多优化?

我以两种方式运行查询并得到上面的结果。 这证明subquery要好得多。

有没有办法比subquery表格结构更好?为什么left join如此糟糕?

0 个答案:

没有答案