MySQL 3表,多个计数分组,但卡住了

时间:2018-06-22 12:25:26

标签: mysql group-by count query-performance

我在查询时遇到了一些麻烦。我正在尝试检索涉及3个表的大型数据库的一些数据。

这些表包含有关添加的数据,在后端网站上,管理员可以管理他要显示的本地添加,位置等信息。这些表组织在3个表中,其中1个表包含所有数据与添加信息有关的信息(名称,可用日期,到期日期等)。然后,还有另外两个表,其中包含一些额外的信息,但仅涉及视图或点击。

所以我只有15个添加项,这些添加项具有多次点击和多次查看。 每次单击和查看表都为每次单击注册一个新行。因此,当单击被注册时,它将添加一个新行,其中addid_views是一个寄存器(单击),而addid是add_table中的addid。例如,添加(1)将具有2个视图和2次点击,而添加(2)将具有1个视图和1次点击。

我的想法是获取每次添加的总点击次数和观看次数。

我有3张这样的桌子:

         adds_table           adds_clicks_table        adds_views_table
    +-------+-----------+   +-------------+------+     +-------------+------+  
    | addid | name      |   | addid_click |addid |     | addid_views |addid |
    +-------+-----------+   +-------------+------+     +-------------+------+
    | 1     | add_name1 |   | 1           | 1    |     | 1           | 1    |
    +-------+-----------+   +-------------+------+     +-------------+------+
    | 2     | add_name2 |   | 2           | 2    |     | 2           | 1    |
    +-------+-----------+
    | 3     | add_name3 |   | 3           | 1    |     | 3           | 2    |
    +-------+-----------+   +-------------+------+     +-------------+------+


CREATE TABLE `bwm_adds` (
  `addid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  ...
  PRIMARY KEY (`addid`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8

CREATE TABLE `bwm_adds_clicks` (
  `add_clickid` int(19) NOT NULL AUTO_INCREMENT,
  `addid` int(11) NOT NULL,
  ...
  PRIMARY KEY (`add_clickid`)
) ENGINE=InnoDB AUTO_INCREMENT=3374 DEFAULT CHARSET=utf8


CREATE TABLE `bwm_adds_views` (
  `add_viewsid` int(19) NOT NULL AUTO_INCREMENT,
  `addid` int(11) NOT NULL,
  ...
  PRIMARY KEY (`add_viewsid`)
) ENGINE=InnoDB AUTO_INCREMENT=2078738 DEFAULT CHARSET=utf8

结果将是一个表,我在其中检索每个添加(addid)的点击次数和观看次数。

我需要获取所有查询,其中包含以下内容:

+-------+---------+-----------+
| addid | clicks  | views     |
+-------+---------+-----------+
| 1     | 123123  | 235457568 |
+-------+---------+-----------+
| 2     | 5124123 | 435345234 |
+-------+---------+-----------+
| 3     | 123541  | 453563623 |
+-------+---------+-----------+

我尝试执行查询,但是卡住并在未定义的时间内加载...我很确定我的查询失败,原因是如果我删除一个计数,则很快显示一些数据。

SELECT a.addid, COUNT(ac.addid_clicks) as 'clicks', COUNT(av.addid_views) as 'views'
        FROM `adds_table` a 
        LEFT JOIN `adds_clicks_table` ac ON a.addid = ac.addid_click
        LEFT JOIN `adds_views_table` av ON ac.addid_click = av.addid_views
                GROUP BY a.addid

Mysql一直在加载,有什么主意可以帮助我了解我所缺少的吗?

顺便说一句,我发现documentation在处理与我几乎相同的问题的地方,您可以看到我的查询与第一个答案非常相似,但是我收到了正在加载的消息每时每刻。没有错误,只需加载。

编辑:我放错了数字并感到困惑。现在表格已修复,我添加了一些解释。

Edit2 :我用SHOW CREATE TABLES DEFINITIONS更新了帖子。

Edit3 :有什么方法可以优化此查询?看来它检索到了我想要的结果,但是mysql数据库取消了查询,因为它要执行30秒钟以上。

SELECT a.addid,
       (SELECT COUNT(addid) FROM add_clicks where addid =  a.addid) as clicks,
       (SELECT COUNT(addid) FROM add_views  where addid =  a.addid) as views
    FROM adds a ORDER BY a.addid;

3 个答案:

答案 0 :(得分:1)

如果这些表确实是您的表(一列,再加上一个auto_inc),则没有有意义的信息证明有3个表而不是1个表:

CREATE TABLE `bwm_adds` (
  `addid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  clicks INT UNSIGNED NOT NULL,
  views  INT UNSIGNED NOT NULL,
  PRIMARY KEY (`addid`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8

然后是UPDATE ... SET views = views + 1(例如),而不是插入其他表中。

答案 1 :(得分:0)

如果您使用的是旧版本,

        SELECT  a.addid, 
                ( SELECT  COUNT(addid_clicks)
                    FROM  `adds_clicks_table`
                    WHERE  addid = a.addid 
                ) AS 'clicks', 
                ( SELECT  COUNT(addid_clicks)
                    FROM  `adds_views_table`
                    WHERE  addid = a.addid 
                ) AS 'views'
            FROM  adds_table AS a

对于5.6及更高版本,这可能会更快:

SELECT  a.addid, c.clicks, v.views
    FROM  `adds_table` a
    LEFT JOIN ( SELECT addid, COUNT(addid_clicks) FROM addid_clicks ) AS c USING(addid)
    LEFT JOIN ( SELECT addid, COUNT(addid_views)  FROM addid_views )  AS v USING(addid)

如果得到NULLs但更喜欢0s,则将值包装在IFNULL(..., 0)中。

如果您需要进一步讨论,请提供SHOW CREATE TABLEEXPLAIN SELECT ...

答案 2 :(得分:0)

我以解决问题的方式结束了。我试图访问的表太大导致了工程数据库的损坏,在adds_views_table中,对于每个视图,都会添加一个新行。以将近300万行和一个表占整个数据库的35%(326MB)作为结尾。

当phpmyadmin尝试执行查询时,由于超时限制适用于mysql,因此永远加载并且永远不会显示结果。更改此值将有所帮助,但无法检索该数据并将其显示在网站上(这意味着在执行查询之前不会加载该网站或数据)。

由于在adds_table中创建了addid索引,该问题已得到解决。另外,如果出于某种原因使用子查询,查询速度会更快。查询结束如下:

SELECT a.addid,
(SELECT COUNT(addid) FROM adds_clicks_table WHERE addid = a.addid) AS 'clicks',(SELECT COUNT(addid) FROM adds_views_table WHERE addid = a.addid) AS 'views'
FROM adds_table a
ORDER BY a.addid;

感谢@Rick James发布了类似的查询,我结束了对其的修改以获取所需的数据

原谅我那可怕的英语