テーブル内のユーザーごとのエントリ数を減らし、各ユーザーに最新のもの (たとえば 10) のみを残す必要があります。サブグループ ( で定義) 内のエントリに番号を付ける必要があり、これはuser_id
MySQL では非常にトリッキーな作業です。私はこのようなことを試しました:
SET
@prev_user := '',
@counter := 0
;
INSERT tmp_table_ordered
SELECT
@counter := CASE WHEN @prev_user = user_id THEN @counter + 1 ELSE 1 END AS counter,
@prev_user := user_id AS prev_user,
entry_id, timestamp, user_id, field_1, field_2
FROM table
ORDER BY user_id, timestamp DESC
;
いくつかのテストテーブル(〜200万レコード)でMyISAM(〜20秒)でかなりうまく機能しましたが、InnoDBに切り替えると、実行時間が桁違いに増加しました(〜6分)。インデックスをいじってみましたが、タスクが長くなるだけでした。このコードは最適ではありませんか? タスクをより適切に解決することは可能ですか?
編集:
私はそれをテストしていないクエリを遅くするのは変数の処理だと確信していました。驚いたことに、クエリを遅くしたのは変数ではありません。遅いのは選択でさえありませんが、時間がかかるのは InnoDB テーブルの挿入です! ターゲット テーブル タイプのみが MyIsam である場合、挿入時間は再び速くなります。
再度編集:
元のテーブルは次のようになります。
CREATE TABLE IF NOT EXISTS `table` (
`entry_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`user_id` int(11) unsigned NOT NULL,
`field_1` int(10) unsigned DEFAULT '0',
`field_2` int(11) unsigned NOT NULL,
PRIMARY KEY (`entry_id`),
) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;
一時テーブルは次のように作成されます。
CREATE TABLE `tmp_table_ordered` LIKE `table`;