我在 Linux (RHEL) 上使用 MySQL 5.6。数据库客户端是一个 Java 程序。有问题的表(MyISAM 或 InnoDB,两者都尝试过)有一个多列索引,包括两个整数(来自其他表的 id)和一个时间戳。
我想删除在给定日期之前具有时间戳的记录。我发现此操作相对较慢(在具有几百万条记录的表中大约需要 30 秒)。但是我也发现,如果指定索引中的另外两个字段,操作会快很多。那里没有什么大惊喜。
我相信我可以查询两个非时间戳表的索引值,然后循环删除操作,每次指定每个 id 的一个值。我希望这不会花太长时间;我还没试过。但似乎我应该能够让 MySQL 为我做循环。我尝试了表单的查询
delete from mytable where timestamp < '2013-08-17'
and index1 in (select id from foo)
and index2 in (select id from bar);
但这实际上比
delete from mytable where timestamp < '2013-08-17';
两个问题。(1)我可以做些什么来加快仅依赖于时间戳的删除操作?(2) 如果做不到这一点,我可以做些什么来让 MySQL 循环遍历另外两个索引列(并快速完成)?
实际上,我对具有相同数据的 MyISAM 和 InnoDB 表都尝试了此操作——它们的速度大致相同。
提前感谢您对这个问题的任何了解。
编辑:有关表结构的更多信息。这是输出show create table mytable
:
CREATE TABLE `mytable` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`timestamp` datetime NOT NULL,
`fooId` int(10) unsigned NOT NULL,
`barId` int(10) unsigned NOT NULL,
`baz` double DEFAULT NULL,
`quux` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `fooId` (`fooId`,`barId`,`timestamp`)
) ENGINE=InnoDB AUTO_INCREMENT=14221944 DEFAULT CHARSET=latin1 COMMENT='stuff'
这是输出show indexes from mytable
:
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
|mytable| 0 | PRIMARY | 1 | id | A | 2612681 | NULL | NULL | | BTREE | | |
|mytable| 0 | fooId | 1 | fooId | A | 20 | NULL | NULL | | BTREE | | |
|mytable| 0 | fooId | 2 | barId | A | 3294 | NULL | NULL | | BTREE | | |
|mytable| 0 | fooId | 3 | timestamp | A | 2612681 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
编辑:更多信息——“解释”的输出。
mysql> explain delete from mytable using mytable inner join foo inner join bar where mytable.fooId=foo.id and mytable.barId=bar.id and timestamp<'2012-08-27';
+----+-------------+-------+-------+---------------+---------+---------+-------------------------------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------------------------------+------+----------------------------------------------------+
| 1 | SIMPLE | foo | index | PRIMARY | name | 257 | NULL | 26 | Using index |
| 1 | SIMPLE | bar | index | PRIMARY | name | 257 | NULL | 38 | Using index; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE |mytable| ref | fooId | fooId | 8 | foo.foo.id,foo.bar.id | 211 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+-------------------------------+------+----------------------------------------------------+