mysql - Mysql 在两个日期条件之间的非常大的行上计算性能
问题描述
我在 Innodb 中有一个超过 2000 万行的表。
列是
id, viewable_id, visitor, viewed_at
其中viewable_id
和viewed_at
是索引。当我执行以下查询时
SELECT COUNT(*)
FROM views_users
WHERE (viewable_id = 2)
and (viewed_at between '2021-04-19 01:38:37'
and '2021-06-30 01:38:37');
=> 拍摄(3 分 6.72 秒)
解释是
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+------------+------+-----------------------------------------------------------+-------------------------------+---------+-------+---------+----------+-------------+
| 1 | SIMPLE | views_users | NULL | ref | views_users_viewable_id_index,views_users_viewed_at_index | views_users_viewable_id_index | 8 | const | 9554594 | 50.00 | Using where
如何将性能提高到 4 秒以下?
CREATE TABLE views_users (
id int unsigned NOT NULL AUTO_INCREMENT,
viewable_type varchar(255) NOT NULL,
viewable_id bigint unsigned NOT NULL,
visitor text,
collection varchar(255) DEFAULT NULL,
viewed_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (viewable_id)
) ENGINE=InnoDB AUTO_INCREMENT=20995848
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
解决方案
我通过应用MySQL partiotons将性能提高到不到 2 秒。
我使用viewed_at
列按范围分区。将viewed_at
类型从更改timestamp
为datatime
并将其作为主键id
。让 cronjob 在每个月的第一天运行,将最后一个分区重组为另一个分区,依此类推。
推荐阅读
- gltf - 在 gltf 文件中存储法线的最有效方法?
- flutter - Flutter:检查 GPS 定位模式
- javascript - 如何使用java脚本从canvas.js中的图表js数据显示表格。?
- svg - 无法更改 svg 路径中的笔划宽度
- java - Java 14 Record 文档中“浅不可变”的含义
- maven - 我们可以在同一个 pom.xml 文件中执行多个配置文件吗
- python - 如何创建仅包含一个版本的 python/pip 的 python 虚拟环境?
- python - 404 Flask 部署在 2008R2 - iis7
- python - 即使安装了 slack 和 slackclient 模块,也无法从 slack 导入 WebClient?
- javascript - 动画/滑动侧菜单不向左滑动?