【问题标题】:Optimize SQL query with multiple SELECT's使用多个 SELECT 优化 SQL 查询
【发布时间】:2017-01-10 21:24:49
【问题描述】:

以下 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`)
)

【问题讨论】:

  • 您的查询是否正确?您确定不想在主查询 where 子句中包含子查询 where 子句谓词的部分吗?您能描述一下您想要实现的目标吗?
  • 我从来没有使用过多个 SELECT,所以我真的不知道。经过一番谷歌搜索并从这里得到答案,这就是结果。
  • 因此,您可以使用一些措辞来描述您的目标。尝试更新您的问题。
  • 不需要。 Dennis Cheung 为我解决了这个问题。
  • A PRIMARY KEYUNIQUE 键,所以折腾唯一键。

标签: mysql optimization count


【解决方案1】:

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

【讨论】:

  • 哦。哇!我不知道。非常感谢您的回答!如果可以的话我会接受的:)
  • 短:SUM(data_status = 'online') -- 因为布尔值被视为 0(false) 或 1(true)。
  • 非常好的解决方案,Rick James :) 谢谢!
【解决方案2】:

你有这种形式的子查询:

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'

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2021-06-02
    相关资源
    最近更新 更多