gpt4 book ai didi

mysql - 更快地获取按两列分组的最新值

转载 作者:行者123 更新时间:2023-11-29 13:20:39 24 4
gpt4 key购买 nike

我正在开发一个应用程序,该应用程序需要从当前超过 300 万行且仍在计数的表中获取最新值。最新值需要按两列/属性进行分组,因此它运行以下查询:

SELECT 
m1.type,
m1.cur,
ROUND(m1.val, 2) AS val
FROM minuteCharts m1
JOIN
(SELECT
cur,
type,
MAX(id) id,
ROUND(val) AS val
FROM minuteCharts
GROUP BY cur, type) m2
ON m1.cur = m2.cur AND m1.id = m2.id;

数据库服务器相当重量级,但上述查询需要 3,500 毫秒才能完成,而且这个数字还在上升。我怀疑当应用程序刚刚启动时这不是一个真正的问题(因为当时数据库几乎是空的),但它正在成为一个问题,而且我还没有找到更好的解决方案。事实上,关于 SO 的类似问题实际上有类似上面的答案(这可能是开发人员从中得到的)。

有人知道如何更有效地获得相同的结果吗?

更新:我太早提交了。

解释分钟图表

Field   Type                              Null  Key     Default    Extra
id int(255) NO PRI NULL auto_increment
time datetime NO MUL NULL
cur enum('EUR','USD') NO NULL
type enum('GOLD','SILVER','PLATINUM') NO NULL
val varchar(80) NO NULL

id 是主索引,time 上有一个索引。

最佳答案

使用 GROUP BY 的子查询正在执行表扫描和临时表,因为没有索引支持它。

mysql> EXPLAIN SELECT m1.type, m1.cur, ROUND(m1.val, 2) AS val FROM minuteCharts m1 JOIN         (SELECT cur, type, MAX(id) id, ROUND(val) AS val FROM minuteCharts GROUP BY cur, type) m2     ON m1.cur = m2.cur AND m1.id = m2.id;
+----+-------------+--------------+------+---------------+-------------+---------+------------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+---------------+-------------+---------+------------------------+------+---------------------------------+
| 1 | PRIMARY | m1 | ALL | PRIMARY | NULL | NULL | NULL | 1 | NULL |
| 1 | PRIMARY | <derived2> | ref | <auto_key0> | <auto_key0> | 6 | test.m1.cur,test.m1.id | 2 | NULL |
| 2 | DERIVED | minuteCharts | ALL | NULL | NULL | NULL | NULL | 1 | Using temporary; Using filesort |
+----+-------------+--------------+------+---------------+-------------+---------+------------------------+------+---------------------------------+

您可以使用以下索引来改进这一点,首先按 GROUP BY 列排序,然后还包括子查询的其他列以使其成为覆盖索引:

mysql> ALTER TABLE minuteCharts ADD KEY (cur,type,id,val);

表扫描变成索引扫描(仍然不是很好,但更好),并且临时表消失。

mysql> EXPLAIN ...
+----+-------------+--------------+-------+---------------+-------------+---------+------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+---------------+-------------+---------+------------------------+------+-------------+
| 1 | PRIMARY | m1 | index | PRIMARY,cur | cur | 88 | NULL | 1 | Using index |
| 1 | PRIMARY | <derived2> | ref | <auto_key0> | <auto_key0> | 6 | test.m1.cur,test.m1.id | 2 | NULL |
| 2 | DERIVED | minuteCharts | index | cur | cur | 88 | NULL | 1 | Using index |
+----+-------------+--------------+-------+---------------+-------------+---------+------------------------+------+-------------+

如果索引适合您的缓冲池,将获得最佳结果。如果大于缓冲池,查询将不得不在索引扫描期间重复插入和推出页面,这将大大降低性能。

<小时/>

回复您的评论:

添加索引需要多长时间的答案取决于您所拥有的 MySQL 版本、该表的存储引擎、您的服务器硬件、表中的行数、并发负载级别数据库等等。换句话说,我无从得知。

我建议使用pt-online-schema-change ,因此您不会有停机时间。

另一个建议是在具有数据库克隆的临时服务器上进行尝试,这样您就可以粗略估计需要多长时间(尽管在空闲服务器上进行测试通常比运行相同的服务器要快得多)在繁忙的服务器上进行更改)。

关于mysql - 更快地获取按两列分组的最新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20907333/

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