发送DELETE查询时,innoDB是从数据库中一次删除数据,还是先创建要删除的数据列表?

时间:2018-12-15 21:44:08

标签: mysql innodb

我有一个约有140,000行的数据库表,现在我正在执行类似的查询

DELETE FROM database WHERE type="delete"

但是要花很长时间。我很想停止查询,看看数据库是否实际上已经缩小,但是我不确定它是否正在创建要删除的数据列表,然后才实际删除数据。收到DELETE查询后,innoDB实际上如何从数据库中清除数据?

这是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 个答案:

答案 0 :(得分:1)

根据您的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

您看到的145,699不是(如您在注释中所写)“行的大小”。这是服务器执行查询必须查看的行数。如您所见,它没有任何可使用的索引。因此,不仅要查看要删除的行,还必须查看145,669行。

此外,由于您的type列是TEXT列,因此速度甚至会更慢。如果您打算以这种方式标记要删除的行,则应认真考虑添加TINYINTCHAR(不是TEXT)或其他列来存储行的状态。

更笼统地说,您确实应该重新考虑其中某些列类型。我严重怀疑您是否需要2^16 - 1字节来存储名为name的列。

答案 1 :(得分:1)

  • INDEX已经被提及。
  • TEXT列(其中有4个)可能存储在其他位置,这需要额外的磁盘命中。 (已经提到)。
  • InnoDB会构建一个崩溃列表,以防万一。这可能是最大的费用。
  • 最好删除不超过1000行的数据块。遍历PRIMARY KEY来查找块。
  • 如果这是重复性任务,则还有其他技术。
  • 如果要删除超过一半的表,则:创建新表; INSERT SELECT复制守护者; RENAME TABLE交换; DROP

有关最后三个建议的详细信息,请参见this