首页 > 解决方案 > Mysql 在两个日期条件之间的非常大的行上计算性能

问题描述

我在 Innodb 中有一个超过 2000 万行的表。

列是

id, viewable_id, visitor, viewed_at

其中viewable_idviewed_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 

标签: mysqlsqlcountquery-optimizationdatabase-performance

解决方案


我通过应用MySQL partiotons将性能提高到不到 2 秒。

我使用viewed_at列按范围分区。将viewed_at类型从更改timestampdatatime并将其作为主键id。让 cronjob 在每个月的第一天运行,将最后一个分区重组为另一个分区,依此类推。


推荐阅读