Friday, February 09, 2007

Purging rows on Princiapl Object Access

[Disclaimer:All postings are provided "AS IS" with no warranties, and confer no rights.]

Purging some tables on Crm is simple as calling the delete service and make sure that everything continues running properly, but when you have more than 10 million rows on one table (PrincipalObjectAccess) how do you will be able to take the delete process on stages?

[MS Crm support response: There is an un-supported option that you could try if you want to get rid of all sharing that is currently setup in CRM. You could directly update the PrincipalObjectAccess table and set the AccessRightsMask and InheritedAccessRightsMask columns to 0. Then we have a deletion service that will go through and automatically clean up that table. This is not technically supported, but if you want to remove all sharing this could be an option that you could do.

Ok that is awesome, but how to identify the rows that are not in use or ready to be deleted.

This is one of the Sql scripts to get the total of rows ready to be deleted and terminated

declare @totalRows int
declare @ToDelete int
declare @ToDeleteMarked int

SELECT @totalRows = count( * )
FROM PrincipalObjectAccess (nolock)

SELECT @ToDelete= count( *)
FROM PrincipalObjectAccess (nolock)
where AccessRightsMask = 0
and InheritedAccessRightsMask > 0

SELECT @ToDeleteMarked= count( *)
FROM PrincipalObjectAccess (nolock)
where AccessRightsMask = 0
and InheritedAccessRightsMask = 0

Select @totalRows as TotalRows,
@ToDelete as ToDelete,
(@totalRows - @ToDelete) as RemainingRows,
@ToDeleteMarked as ToDeleteMarked

Using the previous script will give you the totals only the following script is the one that will update your columns and marked the rows for deletion..

[IMPORTANT: Make sure that you have SQL database backups before trying this and know that you may have to restore your databases if you run into issues. Also this can ONLY be done if you want to remove ALL sharing. There is not a way to leave some sharing intact. ]

SELECT top 500000 *
into #TempPOAFROM
PrincipalObjectAccess (nolock)
where AccessRightsMask = 0
and InheritedAccessRightsMask > 0

update PrincipalObjectAccess
set InheritedAccessRightsMask = 0
where rowguid in (Select rowguid from #tempPOA)

drop table #TempPOA

After finishing marking all the rows for deletion, now you can run the delete service, stop the service (not required) then run the following dos command

C:\Program Files\Microsoft CRM\Server\bin\CrmDeletionService.exe -runonce

[NOTE: -runonce = Clean up database right now.]

we schedule the deletion service to run only once a day, on a business downtime, this process will keep your tables purged and on optimal conditions

regards,
Abe SaldaƱa