如何优化此DB操作?

时间:2014-01-08 11:50:44

标签: mysql sql join sql-delete exists

我对数据库很草率,不能用连接工作,我甚至不确定会更快......

DELETE FROM atable 
WHERE  btable_id IN (SELECT id 
                     FROM   btable 
                     WHERE  param > 2) 
       AND ctable_id IN (SELECT id 
                         FROM   ctable 
                         WHERE  ( someblob LIKE '%_ID1_%' 
                                  OR someblob LIKE '%_ID2_%' )) 

Atable包含~19M行,这将删除~3M。目前,我只能使用LIMIT 100000运行查询,我不想整天坐在这里与phpmyadmin,因为每次删除(100.000行)大约运行1.5分钟。

有什么方法可以加快/自动化它?

MySQL 5.5

(如果任何表包含20M行,你认为它的DB设计已经很糟糕了吗?)

4 个答案:

答案 0 :(得分:2)

使用EXISTSJOIN代替IN来提高效果 使用EXISTS:

DELETE FROM Atable A 
WHERE EXISTS (SELECT 1 FROM Btable B WHERE A.Btable_id = B.id AND B.param > 2) AND 
      EXISTS (SELECT 1 FROM Ctable C WHERE A.Ctable_id = C.id AND (C.someblob LIKE '%_ID1_%' OR C.someblob LIKE '%_ID2_%'))

使用加入:

DELETE A 
FROM Atable A 
INNER JOIN Btable B ON A.Btable_id = B.id AND B.param > 2
INNER JOIN Ctable C WHERE A.Ctable_id = C.id AND (C.someblob LIKE '%_ID1_%' OR C.someblob LIKE '%_ID2_%')

答案 1 :(得分:1)

除了优化查询之外,您还可以查看索引的良好用法,因为它们可能会阻止全表扫描。

例如,对于BTable,在id和param上创建一个索引。

解释为什么这会有所帮助: 如果数据库必须以未排序的方式查找表中的id和param值,则数据库必须读取所有行。如果数据库读取索引SORTED,它可以以降低的成本查找id和param。

答案 2 :(得分:1)

首先你应该尝试使用exists而不是in。在许多情况下它会更快。

然后你可以尝试做内连接而不是in和exists。

示例:

delete a 
from a 
inner join b on b.id = a.tablebid

最后,如果可能(我不知道你是否有id3,ids)改变或通过别的东西。有时奇怪而复杂的变化有助于优化器。情况何时,子查询...

答案 3 :(得分:1)

我没有看到简单索引在哪里有多大帮助。我会这样做:

delete from atable where id in (
    select
        id
    from
        atable a
        join btable b on a.btable_id = b.id
        join ctable c on a.ctable_id = c.id
    where
        b.param > 2
        and (
            c.someblob LIKE '%_ID1_%' 
            OR c.someblob LIKE '%_ID2_%'
        )
)

更正:我假设你有关于btable和ctable的id的索引(可能,如果它们是主键......)和b.param(如果它是数字的话)。