使用多个SELECT优化SQL查询

时间:2016-09-02 17:27:21

标签: mysql optimization count

以下SQL查询会慢慢减慢我的网站极其!从0-1.5秒到轻松超过20秒。我该如何优化呢?

SELECT DATE(a.datetime_logged) AS date,
(SELECT COUNT(aa.data_status) FROM activity AS aa WHERE aa.id_user = '1' AND DATE(aa.datetime_logged) != CURDATE() AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) AND aa.data_status = 'online') AS status_a,
(SELECT COUNT(aa.data_status) FROM activity AS aa WHERE aa.id_user = '1' AND DATE(aa.datetime_logged) != CURDATE() AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) AND aa.data_status = 'idle') AS status_i,
(SELECT COUNT(aa.data_status) FROM activity AS aa WHERE aa.id_user = '1' AND DATE(aa.datetime_logged) != CURDATE() AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) AND aa.data_status = 'streaming') AS status_s

FROM activity AS a
GROUP BY DATE(a.datetime_logged)
ORDER BY DATE(a.datetime_logged) DESC
LIMIT 40

这是表格:

CREATE TABLE IF NOT EXISTS `activity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_user` int(11) NOT NULL,
  `id_channel` varchar(50) NOT NULL,
  `id_game` int(11) NOT NULL,
  `data_muted_server` tinyint(4) NOT NULL,
  `data_muted_self` tinyint(4) NOT NULL,
  `data_deafen_server` tinyint(4) NOT NULL,
  `data_deafen_self` tinyint(4) NOT NULL,
  `data_suppressed` tinyint(4) NOT NULL,
  `data_status` varchar(10) NOT NULL,
  `data_game` text,
  `datetime_logged` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`),
  KEY `index_datelog` (`datetime_logged`)
)

2 个答案:

答案 0 :(得分:1)

您可以使用sum(case data_status when 'online' then 1 end) as status_a替换嵌套的重子查询

答案 1 :(得分:0)

你有这种形式的子查询:

SELECT COUNT(aa.data_status)
  FROM activity AS aa
 WHERE aa.id_user = '1'
  AND DATE(aa.datetime_logged) != CURDATE()
  AND DATE(a.datetime_logged) = DATE(aa.datetime_logged)
  AND aa.data_status = 'online'

这些是令人讨厌的,特别是如果您的id_userdata_status列的基数很低。 DATE(aa.datetime_logged) != CURDATE()术语使这些查询无法进行查询。

(id_user, data_status, datetime_logged)上尝试复合索引。这可能会有所帮助。

您也可以尝试

SELECT COUNT(aa.data_status)
  FROM activity AS aa
 WHERE aa.id_user = '1'
  AND aa.datetime_logged >= DATE(aa.datetime_logged)
  AND aa.datetime_logged <  DATE(aa.datetime_logged) + INTERVAL 1 DAY
  AND DATE(aa.datetime_logged) != CURDATE()
  AND aa.data_status = 'online'

具有相同的复合指数。这将允许索引扫描。