【问题标题】:How to optimize this DB operation?如何优化这个数据库操作?
【发布时间】:2014-01-26 12:09:13
【问题描述】:

我对数据库很草率,无法使用连接进行此操作,而且我什至不确定这会更快...

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 行,你认为这已经是糟糕的数据库设计了吗?)

【问题讨论】:

  • 行数不是衡量表格设计好坏的标准。您的表格是否标准化?这将是衡量良好表格设计的标准......

标签: mysql sql join sql-delete exists


【解决方案1】:

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

以 BTable 为例,在 id 和 param 上创建索引。

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

【讨论】:

    【解决方案2】:

    我看不出一个简单的索引有多大帮助。我会这样做:

    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(如果它是数字)上有索引。

    【讨论】:

      【解决方案3】:

      使用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_%'))
      

      使用 JOIN:

      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_%')
      

      【讨论】:

      • 带有EXISTS 的那个似乎并没有改善,好吧,平均可能只有几秒钟。我的第二个问题是,我不能指定LIMIT,这样它就会超时。无论如何,谢谢!
      【解决方案4】:

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

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

      例子:

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

      最后是否有可能(我不知道你是否有 id3、ids)来改变 or 其他东西。有时奇怪而复杂的变化有助于优化器。 case when,子查询...

      【讨论】:

        猜你喜欢
        • 2023-02-02
        • 1970-01-01
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多