我需要减少表中每个用户的条目数,只为每个用户留下最新的条目(比如 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`;