我有一个日历,用于根据日期(而不是日期时间)为任何用户存储信息。
在我的网站上,用户可以选择一个特定的日期,并填写该日期的有关他自己的一些信息。
此时,我的表结构如下所示
+----+---------+------------+-----------+
| id | user_id | event_date | data |
+----+---------+------------+-----------+
| 1 | 25 | 2015-08-25 | Some Data |
+----+---------+------------+-----------+
实际上,列数据不存在,而是有多个布尔列,但这种方式更简单。
重要的是,我需要一天为每个用户获取所有数据字段。并且它需要尽可能快。
现在,我只运行以下查询。
SELECT `data` FROM `calendar` WHERE `event_date` = '2015-07-08'
我的问题是,使用这种结构,我的表的大小随着时间的推移逐渐增加,并且从该表中进行选择的速度越来越慢(目前约有2000万行)。
我已经删除了超过一年的数据,但是由于用户数量在增加,因此我的表也是如此。
在网站上,用户可以使用某种重复事件来填写日历,这是一个很小的精度。看起来如下:
对于每个星期一和星期六从[开始日期]到[结束日期],设置
data =“ Some Value”。
因此,我想知道是否使用表结构存储重复事件并不比当前表更好。
我看过this answer(和其他类似的东西)提出了以下结构
假设我有两个表,其中一个称为事件:
ID NAME
1 Sample Event
2 Another Event
还有一个名为events_meta的表,如下所示:
ID event_id meta_key meta_value
1 1 repeat_start 1299132000
2 1 repeat_interval_1 432000
但是这种结构似乎不符合我的需求:
它似乎没有处理异常(该事件在每个星期六重复,但不重复一次)
恐怕从
repeat_start
和repeat_interval
获取日期所需的计算时间将比当前选择时间更长。是否有更好的表结构来存储日期数据?正如我所说,我需要尽快获取特定日期的每个用户的数据。
PS:我的
event_date
列上已经有一个索引。这是查询的解释以及SHOW CREATE TABLE的结果
+----+-------------+----------+------+---------------+------------+---------+-------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------------+---------+-------+--------+-------+
| 1 | SIMPLE | calendar | ref | event_date | event_date | 3 | const | 127591 | NULL |
+----+-------------+----------+------+---------------+------------+---------+-------+--------+-------+
CREATE TABLE IF NOT EXISTS `calendar` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`event_date` date NOT NULL,
`data` varchar(128) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`user_id`,`event_date`),
KEY `event_date` (`event_date`)
)
最佳答案
没有改善。
您有INDEX(event_date)
。真正的“问题”是该EXPLAIN中使用的event_date大约有127K行。从磁盘中获取这么多行需要很长时间。
好的,也许有一种方法可以改进此查询-但这可能是以其他查询为代价的。为了知道提出什么建议(以及是否提出建议),请提供SHOW CREATE TABLE
另一个重要的SELECTs
。
一个典型的一天有几行?一个普通用户有几行?
您是否实际使用了客户端中的所有127K行?还是您做进一步过滤?还是合并(求和,计数等)?也许其中一些内容可以移至SELECT
。