我搜索了Internet和Stack Overflow的麻烦,但找不到一个好的解决方案。
我有一个包含300,000行的表(MySql MyISAM)(一列是blob字段)。
我必须使用:
DELETE FROM tablename WHERE id IN (1,4,7,88,568,.......)
IN
语法中有近30,000个id。
需要近1个小时。它也不会使.MYD文件变小,虽然我删除了10%,所以我运行OPTIMIZE TABLE...
命令。它也持续很长时间......(我应该使用它,因为磁盘空间对我很重要)。
在删除上述数据并恢复空间时,有什么方法可以提高性能? (增加缓冲区大小?哪一个?或者?)
答案 0 :(得分:2)
使用IN
,MySQL将扫描表中的所有行,并将记录与IN
子句进行匹配。将对IN
谓词列表进行排序,数据库中的所有300,000行将针对30,000个ID进行二进制搜索。
如果在临时表上使用JOIN
执行此操作(临时表上没有索引),假设id
被编入索引,则数据库将在300,000记录索引上执行30,000次二进制查找。
因此,针对30,000条记录进行300,000次二进制搜索,或针对300,000条记录进行30,000次二进制搜索...哪个更快?到目前为止,第二个更快。
此外,使用DELETE QUICK
延迟索引重建将导致更快的删除。所有记录都将在数据文件和索引中被标记为已删除,并且不会重建索引。
然后,要恢复空间并在以后重建索引,请运行OPTIMIZE TABLE
。
答案 1 :(得分:1)
IN()
声明中的size of the list可能是原因。您可以将ID添加到临时表并加入以执行删除操作。此外,在使用MyISAM时,您可以使用DELETE QUICK选项来避免在删除时触发索引:
对于MyISAM表,如果使用QUICK关键字,则为存储引擎 在删除期间不合并索引叶子,这可能加快一些 各种删除操作。
答案 2 :(得分:1)
试试这个
DELETE ab, b FROM originaltable AS a INNER JOIN temptable AS b ON a.id= b.id where b.id is null;
这只是一个想法。查询未经过测试。你可以查看google上的语法。
答案 3 :(得分:0)
我认为使其更快的最佳方法是创建一个新表并在其中插入您不想删除的行,然后删除原始表,然后您可以将表中的内容复制到主表
这样的事情:
INSERT INTO NewTable SELECT * FROM My_Table WHERE ... ;
然后,您可以使用RENAME TABLE将副本重命名为原始名称
RENAME TABLE My_Table TO My_Table_old, NewTable TO My_Table ;
然后最后删除原始表
DROP TABLE My_Table_old;