基于毫秒选择时间戳

问题描述 投票:2回答:2

我在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. */

我的问题是:

  1. 我正确地拿起面包屑吗?
  2. 我可以优化DELETE查询,使其运行速度比目前更快。
mysql sql optimization delete-row
2个回答
2
投票

您的查询逻辑是正确的,但我建议不要首先存储毫秒格式,而是在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;

2
投票

选项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

© www.soinside.com 2019 - 2024. All rights reserved.