我在MySQL表中存储时间戳和Android设备发送的一些相关用户数据,其结构如下:
CREATE TABLE IF NOT EXISTS `breadcrumbs` (
`breadcrumbs_id` bigint(20) NOT NULL AUTO_INCREMENT,
`users_id` int(10) NOT NULL,
`timestamp` bigint(20) NOT NULL,
`data` text,
PRIMARY KEY (`breadcrumbs_id`,`users_id`),
KEY `fk_breadcrumbs_users1` (`users_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=468792 ;
Android设备以毫秒为单位发送时间戳,并遵循UTC时间标准来构建时间戳。我一直试图删除超过一个月的面包屑。由于MySQL没有毫秒格式,我一直在使用以下查询:
DELETE FROM breadcrumbs WHERE ((`timestamp`)/1000) < UNIX_TIMESTAMP() - 2592000;
删除记录需要相当长的时间。以下是运行删除查询的结果:
/*382,580 rows affected, 0 rows found. Duration for 1 query: 36.894 sec. */
我的问题是:
DELETE
查询,使其运行速度比目前更快。您的查询逻辑是正确的,但我建议不要首先存储毫秒格式,而是在INSERT
上除以1000(或者存储毫秒和普通的UNIX时间戳格式)。或者,当你使用DATETIME
时,使用FROM_UNIXTIME(timestamp / 1000)
将它存储为INSERT
。然后,在timestamp
列上创建索引,删除应该快得多。
CREATE TABLE IF NOT EXISTS `breadcrumbs` (
`breadcrumbs_id` bigint(20) NOT NULL AUTO_INCREMENT,
`users_id` int(10) NOT NULL,
`timestamp` bigint(20) NOT NULL,
/* Also consider storing `timestamp` as a DATETIME */
/* `timestamp` DATETIME NOT NULL, */
`data` text,
PRIMARY KEY (`breadcrumbs_id`,`users_id`),
KEY `fk_breadcrumbs_users1` (`users_id`),
/* index on timestamp */
INDEX `idx_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=468792 ;
/* Store the timestamp without the milliseconds (or store it both ways in 2 columns) */
INSERT INTO breadcrumbs (`breadcrumbs_id`, `users_id`, `timestamp`, `data`) VALUES (123,123, input_timestamp / 1000, data)
/* Or even better, store it as a MySQL DATETIME */
INSERT INTO breadcrumbs (`breadcrumbs_id`, `users_id`, `timestamp`, `data`) VALUES (123,123, FROM_UNIXTIME(input_timestamp / 1000), data)
作为索引的DATETIME
列,您的DELETE
查询将如下所示:
DELETE FROM breadcrumbs WHERE `timestamp` < NOW() - INTERVAL 1 MONTH;
选项1:在(timestamp)
上添加索引并测试此查询,因此可以使用索引:
DELETE FROM breadcrumbs
WHERE `timestamp` < 1000 * UNIX_TIMESTAMP( NOW() - INTERVAL 1 MONTH ) ;
选项2:使用@Micahel Berkowsi的方法并存储时间戳的一部分,MySQL可以在没有转换的情况下使用。
选项3:当它发布时(它仍在测试中)或MySQL 5.6在日期时间和时间戳列中支持微秒精度时移动到MariaDB 5.3 or 5.5。