mysql—发送删除查询时,innodb是逐条删除数据库中的数据,还是先创建要删除的数据列表?

ar5n3qh5  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(272)

我有一个约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;
flvtvl50

flvtvl501#

基于你的 CREATE 语句中没有索引 type 列。所以,你的问题是因为 WHERE 条款。基本上,您的查询强制数据库服务器查看每一行,以查看 type 列为 "delete" . 这很慢,不管你排了多少行。一个索引会使这变得更快,因为服务器基本上只需要请求所有匹配行的列表,然后只对这些行进行操作。
作为一个非常广泛的经验法则,如果您打算在 WHERE 子句,它应该被索引(当然,也有例外,但这不是基于您发布的内容的例外。)
通过运行 EXPLAIN 查询,如

EXPLAIN DELETE FROM database WHERE type="delete"

根据你的评论 EXPLAIN 返回如下内容:

id   select_type   table    partitions   type   possible_keys   key     key_len   ref    rows     filtered  Extra
1    SIMPLE        images                ALL    null            null    null      null   145669             Using where

您看到的145699不是(如您在注解中所写的)“行的大小”,而是服务器执行查询时必须查看的行数。如您所见,它没有任何可以使用的索引。因此,它不是只查看要删除的行,而是查看145669行。
还有,自从你 type 列是一个 TEXT 列,这会更慢。你应该认真考虑添加一个 TINYINT , CHAR (不是 TEXT ),或其他列来存储行的状态(如果您打算以这种方式标记要删除的行)。
一般来说,您确实应该重新考虑其中一些列类型。我很怀疑你是否需要 2^16 - 1 名为的列的字节数 name ,例如。

6yt4nkrj

6yt4nkrj2#

INDEX 已经提到了。 TEXT 列(其中有4个)可能存储在其他地方,需要额外的磁盘命中(已经提到)。
innodb建立了一个列表,列出了在崩溃时要撤销的东西;这可能是最大的成本。
以不超过1000行的块删除是一个更好的主意。穿过街道 PRIMARY KEY 找到大块。
如果这是一个重复的任务,还有其他的技巧。
如果删除的表超过,比如说,表的一半,那么:创建新表; INSERT SELECT 抄袭保管人; RENAME TABLE 交换; DROP .
关于最后三条建议的详细信息,请参见本文。

相关问题