基于毫秒选择时间戳

时间:2012-11-13 13:23:37

标签: mysql sql optimization delete-row

我在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查询,使其运行速度比目前更快。

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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 在datetime和timestamp列中支持微秒精度