gpt4 book ai didi

mysql - 使用 SUM、日期范围和分组依据优化 MySQL 查询

转载 作者:可可西里 更新时间:2023-11-01 07:05:35 26 4
gpt4 key购买 nike

我有下表:

CREATE TABLE IF NOT EXISTS stats (
date date NOT NULL DEFAULT '0000-00-00',
cid int(8) NOT NULL DEFAULT '0',
v bigint(15) NOT NULL DEFAULT '0',
c bigint(15) NOT NULL DEFAULT '0',
a bigint(15) NOT NULL DEFAULT '0',
PRIMARY KEY (date,cid),
KEY date (date),
KEY cid (cid),
KEY date_cid_vca (date,cid,v,c,a)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

这个表有30,842,712

CREATE TABLE IF NOT EXISTS camp (
id int(8) NOT NULL AUTO_INCREMENT,
name varchar(80) NOT NULL DEFAULT '',
PRIMARY KEY (id,name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

这个表有1985

我有以下查询:

SELECT
c.id,
c.name,
SUM(s.v) AS sumv,
SUM(s.c) AS sumc,
GREATEST(((SUM(s.c)/SUM(s.v))*100.00), 0.00) AS cratio,
SUM(s.a) AS suma,
GREATEST(((SUM(s.a)/SUM(s.c))*100.00), 0.00) AS aratio
FROM
stats s, camp c
WHERE
s.date >= '2012-02-01' AND
s.date <= '2012-02-29' AND
c.id=s.cid
GROUP BY s.cid;

EXPLAIN 显示:

+----+-------------+-------+-------+-------------------------------+--------------+---------+---------------------+---------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------------------+--------------+---------+---------------------+---------+-----------------------------------------------------------+
| 1 | SIMPLE | s | range | PRIMARY,date,cid,date_cid_vca | date_cid_vca | 3 | NULL | 1010265 | Using where; Using index; Using temporary; Using filesort |
| 1 | SIMPLE | c | ref | PRIMARY | PRIMARY | 4 | db.s.cid | 1 | Using index |
+----+-------------+-------+-------+-------------------------------+--------------+---------+---------------------+---------+-----------------------------------------------------------+

问题是查询需要大约 50 秒才能完成,即使它使用索引也是如此。还有其他优化查询的方法吗?

谢谢!

最佳答案

您在使用索引优化此查询方面做得很好。我想您在那个日期范围内确实在 stats 中有超过 100 万行。不幸的是,加入(然后分组)100 万行,即使使用覆盖索引,对数据库的要求也很高。为了获得更好的性能,您需要加强硬件,开始非规范化(将 camp 放在 stats 中以避免连接),或者继续为每个营地运行总计而不是即时计算。

编辑

由于删除 100 万多个连接似乎产生了很大的影响,您可以尝试这样的事情:

SELECT c.*, a.* FROM
(SELECT
SUM(s.v) AS sumv,
SUM(s.c) AS sumc,
GREATEST(((SUM(s.c)/SUM(s.v))*100.00), 0.00) AS cratio,
SUM(s.a) AS suma,
GREATEST(((SUM(s.a)/SUM(s.c))*100.00), 0.00) AS aratio,
s.cid
FROM
stats s
WHERE
s.date >= '2012-02-01'
AND s.date <= '2012-02-29'
GROUP BY s.cid) a
JOIN
camp c
ON c.id = a.cid

此查询对较小的结果集进行连接。

关于mysql - 使用 SUM、日期范围和分组依据优化 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9330204/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com