Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics CRM (Archived)

Cleaning up AsyncOperationBase

(0) ShareShare
ReportReport
Posted on by 311

Hi,

I started cleaning my DB in CRM 2013 and found out that AsyncOperationBase is one of the biggest tables. It contains logs of workflows, bulk deletions etc.  Our table had cca 30 mil records. Than I found the script for deleting the records here: https://support.microsoft.com/en-us/help/968520/performance-is-slow-if-the-asyncoperationbase-table-becomes-too-large .

Script  finds 10,000 completed operations in AsyncOperationBase, then it deletes all connected logs in  BulkDeleteFailureBase, WorkflowLogBase etc and in the end it cleans also AsyncOperationBase.  And repeats it until all the records are deleted.

I added few lines to the script to display duration of one round and I was surprised that it took longer for each set of 10k logs after a while. E.g In the beginning I needed like 6 seconds for a round. After 30 rounds I needed like a minute. In my opinion it should be actually faster after every round because the connected tables have less and less records every time 10k records are processed.

My question:

1) why at the end of each iteration the temp table @DeletedAsyncRowsTable is not cleaned? Looks like same ids are cleaned again and again. So in first iteration 10k indexes are looked for in e.g WorkflowLogBase, than 20k, than 30k in next iterations

2) What is the purpose of the index creation in the beginning("CRM_AsyncOperation_CleanupCompleted")? I mean if almost all records in the table satisfy condition:

"OperationType in (1, 9, 12, 25, 27, 10)
AND StateCode = 3
AND StatusCode in (30, 32)
"

isn't than the creation of index and maintaining the index  while deleting making everything slower?

*This post is locked for comments

  • Nikica Profile Picture
    Nikica 311 on at
    RE: Cleaning up AsyncOperationBase

    Of course , there is question about impact to Microsoft support to my database if I change this script, but this deletion in the end practically equals to restarting the script which I anyhow need to do because it is broken already.

  • Nikica Profile Picture
    Nikica 311 on at
    RE: Cleaning up AsyncOperationBase

    Hi Alex,

    thanx for your effort. It's not easy to find somebody who would look so deeply into this scripts.

    Your assumption makes sense, but I added some printout in the end:

    if(@DeleteRowCount > @rowsAffected)
      return
    else
    BEGIN
        set @myInt = (select COUNT(*) from @DeletedAsyncRowsTable)
        SET @delrounds= @delrounds +1
        SET  @strmsg = 'now pausing ' + convert(varchar(25),getdate(),120) + ' round: ' + CONVERT(varchar(10),  @delrounds) + '; items in temp table: ' + CONVERT(varchar(10),  @myInt)
        RAISERROR (  @strmsg, 0, 1) WITH NOWAIT
        WAITFOR DELAY '00:00:05.000'
    END
    end

     

    and the result was:

    now pausing 2017-12-14 17:04:05 round: 1; items in temp table: 10000
    .....

    now pausing 2017-12-14 17:04:26 round: 2; items in temp table: 20000
    ....

    now pausing 2017-12-14 17:04:41 round: 3; items in temp table: 30000

    .........

    now pausing 2017-12-14 18:31:40 round: 157; items in temp table: 1570000
    ...

    now pausing 2017-12-14 18:33:38 round: 158; items in temp table: 1580000

    this is where the script broke due to deadlocking with another process.

     

    so it looks like scope of this table is the whole session, not only the cycle.

     

    As for Index, I don't have opportunity to test it without and with the index, but anyhow, I think that this increase of temp table is main reason of long duration of the script. Due to not cleaning the temp table, somewhere in the middle of my script I'd have 15,000,000 x 15,000,000 comparisions (225 trillions). So I think I need to add some "delete * from @DeletedAsyncRowsTable" at the end of every cycle.

  • ashlega Profile Picture
    ashlega 34,475 on at
    RE: Cleaning up AsyncOperationBase

    Hi,

     I'm pretty sure @DeletedAsyncRowsTable is "unique" for every while cycle - it's a table variable, and it's declared within while.. basically, it's re-declared for every cycle.. So you are not supposed to have more than 10000 there

    while(1=1)

    begin

    declare @DeleteRowCount int = 10000

    declare @rowsAffected int

    declare @DeletedAsyncRowsTable

     As for the index, you can always try running the script without it and see if it gets faster?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Congratulations 2024 Spotlight Honorees

Kudos to all of our 2024 community stars! 🎉

Meet the Top 10 leaders for December

Congratulations to our December super stars! 🥳

Start Your Super User Journey

Join the ranks of our community heros! 🦹

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,711 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,458 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans