2

Android デバイスから送信されたタイムスタンプと関連するユーザー データを MySQL テーブルに格納しています。その構造は次のとおりです。

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 時間標準に従ってタイムスタンプを作成しています。1 か月以上経過したブレッドクラムを削除しようとしています。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現在よりも高速に実行されるようにクエリを最適化できますか?
4

2 に答える 2

3

オプション 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 または 5.5に移行します。

于 2012-11-13T13:33:18.570 に答える
2

クエリロジックは正しいですが、最初にミリ秒形式を保存せず、代わりに 1000 で除算することをお勧めしますINSERT(または、ミリ秒とプレーン 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;
于 2012-11-13T13:30:48.113 に答える