我有一个约140000行的数据库表,现在我正在执行一个如下的查询
DELETE FROM database WHERE type="delete"
但这需要很长时间。我很想停止查询,看看数据库是否真的缩小了,但我不确定它是否正在创建一个要删除的数据列表,然后才真正删除数据。innodb如何在收到delete查询时从数据库中清除数据?
下面是表的create查询 images
):
CREATE TABLE IF NOT EXISTS `images` (
`imageID` int(11) NOT NULL AUTO_INCREMENT,
`runID_fk` int(11) DEFAULT NULL,
`sequenceID_fk` int(11) DEFAULT NULL,
`cameraID_fk` int(11) DEFAULT NULL,
`data` longblob,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`name` text,
`type` text,
`pcadata` longblob,
PRIMARY KEY (`imageID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
2条答案
按热度按时间jxct1oxe1#
基于你的
CREATE
语句中没有索引type
列。所以,你的问题是因为WHERE
条款。基本上,您的查询强制数据库服务器查看每一行,以查看type
列为"delete"
. 这很慢,不管你排了多少行。一个索引会使这变得更快,因为服务器基本上只需要请求所有匹配行的列表,然后只对这些行进行操作。作为一个非常广泛的经验法则,如果您打算在
WHERE
子句,它应该被索引(当然,也有例外,但这不是基于您发布的内容的例外。)通过运行
EXPLAIN
查询,如根据你的评论
EXPLAIN
返回如下内容:您看到的145699不是(如您在注解中所写的)“行的大小”,而是服务器执行查询时必须查看的行数。如您所见,它没有任何可以使用的索引。因此,它不是只查看要删除的行,而是查看145669行。
还有,自从你
type
列是一个TEXT
列,这会更慢。你应该认真考虑添加一个TINYINT
,CHAR
(不是TEXT
),或其他列来存储行的状态(如果您打算以这种方式标记要删除的行)。一般来说,您确实应该重新考虑其中一些列类型。我很怀疑你是否需要
2^16 - 1
名为的列的字节数name
,例如。nkoocmlb2#
INDEX
已经提到了。TEXT
列(其中有4个)可能存储在其他地方,需要额外的磁盘命中(已经提到)。innodb建立了一个列表,列出了在崩溃时要撤销的东西;这可能是最大的成本。
以不超过1000行的块删除是一个更好的主意。穿过街道
PRIMARY KEY
找到大块。如果这是一个重复的任务,还有其他的技巧。
如果删除的表超过,比如说,表的一半,那么:创建新表;
INSERT SELECT
抄袭保管人;RENAME TABLE
交换;DROP
.关于最后三条建议的详细信息,请参见本文。