删除SQL数据库中的行会增加查询性能吗?

时间:2015-11-24 16:12:13

标签: mysql database performance database-performance

我有一个数据库,其中包含一个跟踪用户状态的表。当我完成处理行时,不再需要将其保留在数据库中并可以删除。

现在假设我想跟踪行而不是删除它(用于历史目的,分析等)。会不会更好:

  1. 将数据保留在同一个表格中,并将该行标记为“已使用”(带有额外的列或类似内容)

  2. 从表中删除行并将其插入到仅为历史目的创建的单独表中

  3. 对于选择#1,我想知道在数据库中留下不必要的行是否会开始影响查询性能。 (我的所有查询都在索引列上,所以这可能没关系?)

    对于选择#2,我想知道不断删除行是否会导致碎片等问题?

2 个答案:

答案 0 :(得分:3)

从长远来看,查询效果会更好:

永久插入会发生什么:

  

表增长,索引增长,索引性能(查找)随表的大小而减小,特别是插入性能受损。

删除时发生了什么:

  

表页面碎片化,因此删除的空间不会像预期的那样100%重复使用,在MySQL中更接近50%。因此,该表仍然增长到您可能对数据量预期的大小的两倍。索引变得支离破碎并变为高边形:它包含新数据,但也包含旧数据的结构。这取决于您的数据结构有多糟糕。然而,这种情况稳定在一定的性能。这个性能点有两个好处:

     

1)该表的大小更受限制,因此潜在的全表扫描更快

     

2)你的表现是可以预测的。

     

由于碎片,但是这个性能点不等于数据量的两倍左右,它往往会更糟糕(基准测试看你自己)。但是,删除方案的好处是因为您拥有较小的数据集,您可以在每个合理的时间段内重建索引一次,从而提高性能。

<强>替代

您可以通过两种方法来提高绩效:

  • 切换到MariaDB:在大型数据集上获得约8%的性能(我的观察,数据集只有大约200GB的压缩数据)

  • 查看分区:如果您有一个方便的分区参数,您可以为您创建一系列“小表”,并防止删除,重建和历史数据管理的逻辑。这可能会为您提供最佳性能配置文件。

答案 1 :(得分:1)

如果该表的大部分标记为已删除,则在您查找未删除的记录时,您将会遇到这些问题。将is_deleted添加到许多索引可能会有所帮助。

如果您完全按年龄删除记录,那么PARTITION BY RANGE(TO_DAYS(...))是构建表格的绝佳方式。 DROP TABLE是即时的,创建新周(或月或...)分区的ALTER TABLE ... REORGANIZE ...也是即时的。有关详细信息,请参阅my blog

如果您“移动”记录到另一个表,那么由于碎片,该表不会很快收缩。如果你有足够的磁盘空间,这不是一个错误的交易。如果某些查询需要同时查看当前和已归档的记录,请使用UNION ALL;它非常简单有效。