【发布时间】:2017-07-18 20:30:19
【问题描述】:
我有以下查询导致 CPU 使用率达到最大值(严重降低服务器上运行的其他所有内容的性能)并且需要几分钟才能运行。
INSERT INTO cache (`time`, name, price, low, high, week, month, season)
SELECT
MAX(`time`) AS `time`,
name,
MIN(CASE WHEN `time` = 1500254967 THEN price ELSE 999999 END) AS price,
MIN(price) AS low,
MAX(price) AS high,
SUM(CASE WHEN `time` > 1499650167 AND price = 1 THEN 1 ELSE 0 END) / SUM(CASE WHEN `time` > 1499650167 THEN 1 ELSE 0 END) AS week,
SUM(CASE WHEN `time` > 1497835767 AND price = 1 THEN 1 ELSE 0 END) / SUM(CASE WHEN `time` > 1497835767 THEN 1 ELSE 0 END) AS month,
SUM(CASE WHEN `time` > 1499995767 AND price = 1 THEN 1 ELSE 0 END) / SUM(CASE WHEN `time` > 1499995767 THEN 1 ELSE 0 END) AS season
FROM low_price
GROUP BY name;
解释告诉我:
+----+-------------+-----------+-------+---------------+----------+---------+------+----------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+----------+---------+------+----------+-------+
| 1 | SIMPLE | low_price | index | idx_name | idx_name | 603 | NULL | 20875117 | NULL |
+----+-------------+-----------+-------+---------------+----------+---------+------+----------+-------+
在我的非专家眼中看起来不错。
low_price 表中有 1200 万行可供选择。理想情况下,应该允许这个表从这里开始增长,但可以将它修剪到这个大小作为最大值。使其更小将导致数据丢失。我们可以每天一次而不是每小时一次来获取数据,以使其大小变为原来的 1/24,但如果有其他方法,我不希望这样做。
表定义为:
CREATE TABLE `low_price` (
`time` int(11) DEFAULT NULL,
`price` int(11) DEFAULT NULL,
`name` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE `cache` (
`time` int(11) DEFAULT NULL,
`name` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`high` int(11) DEFAULT NULL,
`low` int(11) DEFAULT NULL,
`price` int(11) DEFAULT NULL,
`week` double DEFAULT NULL,
`month` double DEFAULT NULL,
`season` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
此查询不会在用户时间运行。它正在设置在用户时间使用的缓存表。因此,加快速度的最佳选择的替代方法就是告诉它“嘿,不要使用这么多 CPU”。我有点讨厌走那条路,因为它所花费的时间已经很长了,以至于它会开始在每小时运行时自行运行。
你对我有什么建议吗?生成此表的替代样式或改进此特定 INSERT 的注意事项?谢谢!
【问题讨论】:
-
我会尝试在没有 CASE 语句的情况下运行它,看看你得到了多少改进。
-
谢谢。由于某种原因,删除 CASE 似乎没有多大帮助。可能是因为 MAX 和 MIN 仍然导致我扫描所有数据?以下答案中建议的索引确实有帮助。
-
@JeffUK - 到目前为止,获取行是任何查询的主要部分。这个查询需要获取所有行。
标签: mysql sql database performance