从争用表中删除行

时间:2009-10-30 12:28:21

标签: sql oracle delete-row

我有一个数据库表,其中每一行都有一个随机生成的主键,一条消息和一个用户。每个用户有大约10-100条消息,但有10k-50k用户。

我每天为每个用户编写消息。我想在写新内容之前丢弃每个用户的旧消息,以使表格尽可能小。

现在我有效地做到了这一点:

delete from table where user='mk'

然后为该用户编写所有消息。我看到很多争用,因为我有很多线程在同一时间这样做。

我还需要为每个用户保留最新的邮件集。

我无法直接访问数据库。我试图根据一些二手反馈来猜测问题。我关注这个场景的原因是删除查询显示了很多等待时间(再次 - 据我所知),加上它是一个新增的功能。

有人可以提供任何建议吗?

是否会更好:

select key from table where user='mk'

然后从那里删除单个行?我认为这可能导致更少的残酷锁定。

7 个答案:

答案 0 :(得分:4)

如果您每天都为每个用户执行此操作,为什么不在一个语句中删除表中的每条记录?甚至

truncate table whatever reuse storage
/

修改

我建议这种方法的原因是,该过程看起来像每天批量上传用户消息,然后清除旧消息。也就是说,业务规则在我看来是“表格只能为任何给定用户保留一天的消息”。如果为每个用户完成此过程,那么单个操作将是最有效的。

但是,如果用户每天都没有获得一组新的消息,则有一个子规则要求我们为每个用户保留最新的消息集,然后切换整个表格是错的。

答案 1 :(得分:3)

不,最好在一组行上执行单个SQL语句,而不是一系列“逐行”(或Tom Kyte称之为“慢速慢”)操作。当你说你“看到很多争论”时,你究竟看到了什么?一个显而易见的问题:列是否已编入索引?

(当然,列名在Oracle数据库中实际上不是USER,因为它是一个保留字!)

编辑:您已经说过,USER列未编入索引。这意味着每次删除都将涉及最多50K * 100 = 500万行(或最多10K * 10 = 100,000行)的全表扫描,以删除仅10-100行。在USER上添加索引可以解决您的问题。

答案 2 :(得分:0)

你确定你看到了锁定争用吗?由于太多并发(但不相关的更新),您似乎更有可能看到磁盘争用。解决方案就是减少您使用的线程数量:减少磁盘争用意味着更高的总吞吐量。

答案 3 :(得分:0)

我认为您需要更清楚地定义您的要求......

例如。如果您知道要为其写入消息的所有用户,请将ID插入临时表,将其编入索引并批量删除。然后,你正在解雇的线程正在做两件事。将用户的ID写入临时表,将消息写入另一个临时表。然后当线程完成执行时,主线程应该

DELETE * FROM消息INNER JOIN TEMP_MEMBERS ON ID = TEMP_ID

INSERT INTO MESSAGES SELECT * FROM TEMP_messges

我不熟悉Oracle语法,但如果用户消息全部快速连续完成,那就是我接近它的方式。

希望这有帮助

答案 4 :(得分:0)

与您的DBA对话

他在那里帮助你。当我们DBA从开发人员那里获取此类内容时,我们假设我们将为您提供该任务的支持。如果您的代码花费的时间太长而且时间似乎与数据库有关,那么您的DBA将能够准确地查看正在发生的事情并提供建议,甚至可以在不更改任何内容的情况下解决问题。

只是浏览一下您的问题陈述,看起来您没有看到争用问题,但我对您的底层结构一无所知。

真的,和你的DBA谈谈。他可能会喜欢看一些有趣的事情,而不是计划最新的CPU部署。

答案 5 :(得分:-2)

这可能会加快速度:

创建一个查找表:

create table rowid_table (row_id ROWID ,user VARCHAR2(100));
create index rowid_table_ix1 on rowid_table (user);

夜间工作:

truncate table rowid_table;
insert /*+ append */ into rowid_table
select ROWID row_id , user
from table;
dbms_stats.gather_table_stats('SCHEMAOWNER','ROWID_TABLE');

然后删除记录时:

delete from table
where ROWID IN (select row_id
                from rowid_table
                where user = 'mk');

答案 6 :(得分:-4)

你自己的建议似乎很明智。小批量锁定有两个好处:

  • 交易将更小
  • 锁定将限制为一次只有几行

批量锁定应该是一个很大的改进。