提高 delete with IN 性能

Improve delete with IN performance

我很难在 MariaDB 5.5.44 数据库中编写 DELETE 查询。

以下两个代码示例中的第一个效果很好,但我需要在其中添加一个 WHERE 语句。这显示在第二个代码示例中。

我只需要删除 polozkyTransakcipuvodFaktury <> FAKTURA VO CZ 中的行在 transakce_tmp table 中。我认为我在第二个示例中的 WHERE 语句可以与内部 SELECT 正常工作,但它需要永远处理(在我基于云的 ETL 工具中需要大约 40 分钟),即使这样它也不会离开我希望保持不变的行。

1.

DELETE FROM polozkyTransakci
WHERE typPolozky = 'odpocetZalohy';

2.

DELETE FROM polozkyTransakci
WHERE typPolozky = 'odpocetZalohy'
     AND idTransakce NOT IN (
 SELECT idTransakce
 FROM transakce_tmp
 WHERE puvodFaktury = 'FAKTURA VO CZ');

感谢一百万的帮助

大卫

IN 的性能非常差.. 尝试使用 NOT EXISTS()

DELETE FROM polozkyTransakci 
WHERE typPolozky = 'odpocetZalohy'
     AND NOT EXISTS (SELECT 1
                     FROM transakce_tmp r
                     WHERE r.puvodFaktury = 'FAKTURA VO CZ'
                          AND r.idTransakce = polozkyTransakci.idTransakce );

我可能倾向于将查询写成 LEFT JOIN,虽然我猜这将具有与 NOT EXISTS:

相同的性能计划
DELETE pt
    FROM polozkyTransakci pt LEFT JOIN
         transakce_tmp tt
         ON pt.idTransakce = tt.idTransakce AND
            tt.puvodFaktury = 'FAKTURA VO CZ'
    WHERE pt.typPolozky = 'odpocetZalohy' AND tt.idTransakce IS NULL;

如果您没有索引,我会推荐它们:polozkyTransakci(typPolozky, idTransakce)transakce_tmp(idTransakce, puvodFaktury)。这些也适用于 NOT EXISTS 版本。

您可以使用 SELECT:

测试这些查询的性能
    SELECT pt.*
    FROM polozkyTransakci pt LEFT JOIN
         transakce_tmp tt
         ON pt.idTransakce = tt.idTransakce AND
            tt.puvodFaktury = 'FAKTURA VO CZ'
    WHERE pt.typPolozky = 'odpocetZalohy' AND tt.idTransakce IS NULL;

DELETE 应该更慢(由于记录事务的成本),但性能应该相当。

在进行性能调整之前,您需要弄清楚为什么它没有删除正确的行。

所以首先开始做 selects,直到你找到正确的行。建立你的 select 一点时间检查每个阶段的结果,看看你是否得到你想要的结果。

获得 select 后,即可转换为删除。在测试删除时,它是一个事务,运行 对遗留的数据进行一些测试,以确保在回滚或提交之前正确删除它。由于您可能想要性能调整,我建议回滚,这样您就可以再次尝试性能调整版本,以确保获得相同的结果。当然,您只想在开发服务器上执行此操作!

虽然我同意 not exists 可能更快,但您还想看看其他一些内容:

  • 你有级联删除吗?如果你最终删除了很多 子记录,这可能是问题的一部分。
  • 是否有影响删除的触发器?尤其要看看是否有人将一个设置为 运行 逐行而不是一组。当您删除许多记录时,逐行触发器是一件非常糟糕的事情。例如,假设您正在删除 50K 条记录,并且您有一个审计 table 的删除触发器。如果它一次向 table 插入一条记录,它将被执行 50K 次。如果它一步插入所有已删除的记录,则单独插入可能需要更长的时间,但总执行时间要短得多。
  • 你有什么索引,它有助于删除吗?
  • 您需要检查每个查询的解释计划,以便 看看他们是否正在改进查询方式的细节 执行。

性能调优是一件复杂的事情,最好通过阅读一些适用于您的特定数据库的性能调优书籍来详细了解它。