Mysql 计算两个日期条件之间非常大的行的性能
Mysql count performance on very big rows between two dates conditions
我有一个 table 在 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');
=> take (3 min 6.72 sec)
解释是
| 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
对于此查询:
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';
您可以创建一个索引:
CREATE INDEX idx_views_users_viewable_id_viewed_at ON views_users(viewable_id, viewed_at);
我通过应用 MySQL partiotons 将性能提高到不到 2 秒。
我使用 viewed_at
列按范围分区。将 viewed_at
类型从 timestamp
更改为 datatime
并将其作为 id
的主键。
使 cronjob 在每个月的第一天运行,将最后一个分区重组为另一个分区,依此类推。
我有一个 table 在 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');
=> take (3 min 6.72 sec)
解释是
| 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
对于此查询:
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';
您可以创建一个索引:
CREATE INDEX idx_views_users_viewable_id_viewed_at ON views_users(viewable_id, viewed_at);
我通过应用 MySQL partiotons 将性能提高到不到 2 秒。
我使用 viewed_at
列按范围分区。将 viewed_at
类型从 timestamp
更改为 datatime
并将其作为 id
的主键。
使 cronjob 在每个月的第一天运行,将最后一个分区重组为另一个分区,依此类推。