如何从巨大的MySQL表中删除匹配条件的行?

时间:2017-02-13 16:52:38

标签: mysql sql-delete database-indexes

我在我的一个应用程序中使用MySQL数据库,其中一个表的大小约为10GB。我想删除符合条件的此表中的行。删除查询的格式为:

Delete from table_name
where (a,b,c) in ((1,2,3),(1,5,6));

字段(a,b,c)上有一个复合索引。查询需要几分钟来删除行,而我希望操作在几毫秒或几秒内完成。我怎样才能做到这一点?字段上的单个索引是否会比多列索引更快?

我的意思是如果查询如下:

Delete from table_name
where a = 1 and (b,c) in ((2,3),(5,6));

这会给出更快的结果吗?

1 个答案:

答案 0 :(得分:0)

如果(a,b,c)有一组不同的值,则可以对这些值进行分区。 List Columns Partitioning. 在对表进行分区后,“删除”将改为删除分区,并且速度非常快。

  

MySQL 5.7支持LIST COLUMNS分区。这是LIST分区的一种变体,它允许使用多个列作为分区键,并将整数类型以外的数据类型列用作分区列;

文档中的示例表:

CREATE TABLE customers_1 (
   first_name VARCHAR(25),
   last_name VARCHAR(25),
   street_1 VARCHAR(30),
   street_2 VARCHAR(30),
   city VARCHAR(15),
   renewal DATE
)
PARTITION BY LIST COLUMNS(city) (
   PARTITION pRegion_1 VALUES IN('Oskarshamn', 'Högsby', 'Mönsterås'),
   PARTITION pRegion_2 VALUES IN('Vimmerby', 'Hultsfred', 'Västervik'),
   PARTITION pRegion_3 VALUES IN('Nässjö', 'Eksjö', 'Vetlanda'),
   PARTITION pRegion_4 VALUES IN('Uppvidinge', 'Alvesta', 'Växjo')
);

我在文档中找不到使用多列作为分区键的示例,但正如您所料,它看起来像......

CREATE TABLE customers_2 (
    first_name VARCHAR(25),
    last_name VARCHAR(25),
    street_1 VARCHAR(30),
    street_2 VARCHAR(30),
    city VARCHAR(15),
    renewal DATE
)
PARTITION BY LIST COLUMNS(first_name,last_name) (
    PARTITION me_partition VALUES IN(('Alden','W'),('Aldino','W')),
    PARTITION you_partition VALUES IN(('Pooja','Gupta'),('PJ','Gupta'))
);

要分区表,你可以使用一些花哨的裤子动态sql。

SET SESSION group_concat_max_len = 1000000000;
SET @i = 0;
SELECT CONCAT('ALTER TABLE customers_2
PARTITION BY LIST COLUMNS(first_name,last_name) (
    ',GROUP_CONCAT('PARTITION partition_',@i:=@i+1,' VALUES 
IN((''',d.first_name,''',''',d.last_name,'''))' SEPARATOR 
',\n\t'),'
);')
FROM (
    SELECT DISTINCT first_name, last_name
    FROM customers_2
) d;

这构建了以下alter语句

ALTER TABLE customers_2
PARTITION BY LIST COLUMNS(first_name,last_name) (
    PARTITION partition_1 VALUES IN(('Alden','W')),
    PARTITION partition_2 VALUES IN(('Jon','Smith')),
    PARTITION partition_3 VALUES IN(('Other','Name')),
    ...
);