【问题标题】:Delete with inner join takes more than 40 seconds to delete 500 rows使用内连接删除需要 40 多秒才能删除 500 行
【发布时间】:2019-08-02 14:57:44
【问题描述】:

我有这个要求:

delete L 
from L
inner join M on L.id = M.ref_id 
             or L.id = M.news_id 

完成删除 588 行需要 39 到 50 秒。

如果在我的查询中将delete L from L 替换为select * from L,则选择非常快 0,015 秒

这里是my trace in xml

这里是my explain plan file .SQLPlan

希望你能帮助我在这里缺少什么,这里有什么问题?

【问题讨论】:

标签: sql sql-server tsql join inner-join


【解决方案1】:

从大型聚簇表中删除行通常很慢。

cmets 中讨论的著名的“BETWEEN”是聚集索引的一个分区,它从您的连接中获取最小值和最大值。所以建议批量删除。

我想可能很少有一般性建议,但它总是 取决于不同的东西,如数据量、硬件、 内存、日志文件大小等 - 批量删除行。最佳批次 大小取决于环境,但通常在 10K 到 100K。 - 按聚集索引的顺序删除 - 可能的话转 您的恢复模式为 BULK/SIMPLE 以实现最少的日志记录。 - 如果可能的话 从子表中删除诸如外键约束之类的约束。 - 如果可能,禁用非聚集索引 - 取决于数量 您要删除的数据,可能最好导出 数据到一个新表,然后删除旧表或保留它 不同的名称以供将来参考。如您所见,主要是 视情况和环境而定。

这是最好的答案,“也许你需要调整系统,而不是查询”

但从删除语句中,我更愿意看到大部分成本 来自删除本身。明白了,聚集索引在哪里 数据存储在具有聚集索引的表中。当你 删除,您正在从集群中删除。这并不是说你 可能无法进一步调整,但你看到的很正常, 甚至是可取的行为。没有看到你在做什么, 很难提出建议,但可能是你在做 好的。在这种情况下,也许您需要调整系统,而不是 询问。获得更快的磁盘。确保您没有承受内存压力。 检查您的等待统计信息,了解大部分工作在哪里完成 在服务器上并从那里进行调整。

如果你不能做任何这些事情,使用循环逐行删除可能会更快......

来源:https://ask.sqlservercentral.com/questions/90223/how-to-reduce-the-cost-of-clustered-index-delete.html

【讨论】:

    【解决方案2】:

    如果它真的很慢是因为加入,而不是因为删除本身很慢,我发现通过将中间结果计算到表变量中来欺骗 SQL 生成更优化的查询很有用,然后处理它表变量。

    DECLARE @temp TABLE
    (
        id int
    );
    
    INSERT INTO @temp
    SELECT id
    from L
    inner join M on L.id = M.ref_id 
             or L.id = M.news_id;
    
    DELETE FROM L WHERE id IN (SELECT id FROM @temp)
    

    【讨论】:

    • @bee 你有没有尝试过:DELETE FROM L WHERE ID IN (SELECT ref_id FROM M) OR ID IN (SELECT news_id FROM M) 并尝试添加 3 个索引 id、news_id、ref_id
    • IN () 子句是实现这一目标的坏方法(ps:相同或最差的结果)
    • 这比原来更糟糕 - 仍然执行 JOIN,但现在,优化器 没有 索引或统计信息可用于优化 DELETE。
    • @pascalsanchez 我只是建议它,因为偶尔我会遇到 SQL Server 根据其统计数据做出非常糟糕的决定的情况,经过多次尝试修复它,我可以摆脱的唯一方法那些糟糕的优化是使用表变量将查询分成几部分,这样优化器就不会做一些愚蠢的事情。通常在这些情况下,查询非常复杂,但我认为在这里可能值得一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多