我有一个约有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;
答案 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
列,因此速度甚至会更慢。如果您打算以这种方式标记要删除的行,则应认真考虑添加TINYINT
,CHAR
(不是TEXT
)或其他列来存储行的状态。
更笼统地说,您确实应该重新考虑其中某些列类型。我严重怀疑您是否需要2^16 - 1
字节来存储名为name
的列。
答案 1 :(得分:1)
INDEX
已经被提及。TEXT
列(其中有4个)可能存储在其他位置,这需要额外的磁盘命中。 (已经提到)。PRIMARY KEY
来查找块。INSERT SELECT
复制守护者; RENAME TABLE
交换; DROP
。有关最后三个建议的详细信息,请参见this。