Очистка корзины SharePoint
-
09-12-2019 - |
Вопрос
Наша установка SharePoint 2007 имеет особенно огромную корзину первого уровня.Некоторое время назад я написал сценарий PowerShell, который удаляет старые элементы.Просто ради интереса, это опубликовано ниже.
ОБНОВЛЕНИЕ2:
У нас более 42 500 000 записей в таблице «Корзина» в базе данных контента!!
Я выяснил, что наше задание BDLC, которое было запланировано до того, как я присоединился к команде, перекачивало в таблицу RecycleBin столько данных, что даже SharePoint не может управлять этим должным образом без тайм-аута.Даже наш запланированный скрипт может удалять только 1000 записей каждые 30 минут.Посчитай это, а потом пожалей меня.Записей так много, что теперь вы даже не сможете применить квоты без истечения времени ожидания SharePoint.Похоже, нам придется заморозить удаление записей в BDLC.
ОБНОВЛЕНИЕ1: Я выполнил сценарий PowerShell, чтобы удалить каждый элемент, и запустил SQL Profiler, чтобы выяснить это. proc_DeleteRecycleBinItem выполняется, что затрагивает несколько таблиц, поэтому мы будем придерживаться запланированного сценария PowerShell, который будет запускаться и создавать отчеты каждые N минут.
У нас более 38 500 000 записей в таблице «Корзина» в базе данных контента!!
Я считаю, что причина, по которой это так важно, заключается в том, что у нас есть BDLC на уровне 2, синхронизирующий данные из других систем и перерабатывающий удаленные записи.Кроме того, он настолько велик, что даже встроенное задание таймера SharePoint не может его контролировать и время ожидания истекает...
Я знаю, что мафия SharePoint пристрелит меня, если я задам этот вопрос, но...кто-нибудь когда-нибудь удалял строки из фактического RecycleBin
таблицу в базе данных контента SharePoint?У нас 15430792 КБ (14,7 ГБ).
Я знаю, что Microsoft прекратит поддержку, если вы измените базу данных контента.Пожалуйста, не публикуйте это как ответ.Конечно, это не лучшая практика.Этот вопрос ясно звучит:кто-нибудь пробовал?...
Я просто ищу более быстрый способ очистки корзины.Вы можете увидеть мои сценарии ниже, поэтому очевидно, что я пытался их поддерживать.Корзина становится настолько большой, что запуск скриптов занимает целую вечность, потому что данных очень много.
Наши пользовательские данные на самом деле занимают 203790168 КБ (194,3 ГБ), и я написал сценарий PS для получения больших файлов, чтобы я мог управлять и этим размером.Это также ниже, чтобы внести свой вклад в эфир.
Кроме того, у нас есть BDLC (со сторонним инструментом из Layer2), который синхронизирует данные между SQL и обратно.Я считаю, что эта работа регулярно удаляет много данных, из-за чего таблица RecycleBin становится огромной.
Я думаю, что ответ на мой собственный вопрос может быть...что-то вроде...запланируйте задачу для запуска сценария обслуживания, который я уже написал...хм...
function RemoveOldItems-SPFirstStageRecycleBin([string]$url, [int]$rowlimit, [int]$days)
{
$siteCollection = New-Object Microsoft.SharePoint.SPSite($url);
$recycleQuery = New-Object Microsoft.SharePoint.SPRecycleBinQuery;
$recycleQuery.ItemState = [Microsoft.SharePoint.SPRecycleBinItemState]::FirstStageRecycleBin
$recycleQuery.OrderBy = [Microsoft.SharePoint.SPRecycleBinOrderBy]::DeletedDate
$recycleQuery.RowLimit = $rowlimit
$recycledItems = $siteCollection.GetRecycleBinItems($recycleQuery);
$count = $recycledItems.Count;
for($i = 0; $i -lt $count; $i++){
$age = ((Get-Date) - $recycledItems[$i].DeletedDate).Days;
if($age -gt $days){
$g = New-Object System.Guid($recycledItems[$i].ID);
$recycledItems.Delete($g);
}
}
$siteCollection.Dispose()
}
function Get-DocInventory() {
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$farm = [Microsoft.SharePoint.Administration.SPFarm]::Local
foreach ($spService in $farm.Services) {
if (!($spService -is [Microsoft.SharePoint.Administration.SPWebService])) {
continue;
}
foreach ($webApp in $spService.WebApplications) {
if ($webApp -is [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]) { continue }
foreach ($site in $webApp.Sites) {
foreach ($web in $site.AllWebs) {
foreach ($list in $web.Lists) {
if ($list.BaseType -ne "DocumentLibrary") {
continue
}
foreach ($item in $list.Items) {
$data = @{
"Web Application" = $webApp.ToString()
"Site" = $site.Url
"Web" = $web.Url
"list" = $list.Title
"Item ID" = $item.ID
"Item URL" = $item.Url
"Item Title" = $item.Title
"Item Created" = $item["Created"]
"Item Modified" = $item["Modified"]
"Size (kb)" = $item.File.Length/1KB
"Size (gb)" = $item.File.Length/1GB
}
Write-Host $item.Url -ForegroundColor DarkGray
# Only add files larger than 100 MB
if($item.File.Length -gt 100MB){
Write-Host $site.Url + $item.Url -ForegroundColor Red
New-Object PSObject -Property $data
}
}
}
$web.Dispose();
}
$site.Dispose()
}
}
}
}
#Get-DocInventory | Out-GridView
Get-DocInventory | Export-Csv -NoTypeInformation -Path D:\Logs\inventory.csv
$jobName = "Get Large Lists"
function Get-LargeLists() {
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
#create stop watch
[System.Diagnostics.Stopwatch] $sw;
$sw = New-Object System.Diagnostics.Stopwatch
$sw.Start()
$lists = @()
$reportSiteUrl = "http://my-site.gov/sites/applications/reporting/"
$reportListUrl = $reportSiteUrl + "Lists/Large%20Lists/"
$farm = [Microsoft.SharePoint.Administration.SPFarm]::Local
foreach ($spService in $farm.Services) {
if (!($spService -is [Microsoft.SharePoint.Administration.SPWebService])) {continue}
foreach ($webApp in $spService.WebApplications) {
if ($webApp -is [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]) {continue}
foreach ($site in $webApp.Sites) {
foreach ($web in $site.AllWebs) {
foreach ($list in $web.Lists) {
# only add items that have 1000 items or more
if($list.ItemCount -le 99){continue}
# create new object
$o = New-Object Object
Add-Member -InputObject $o -MemberType NoteProperty -Name SiteCollectionUrl -Value $list.ParentWeb.Site.RootWeb.Url
Add-Member -InputObject $o -MemberType NoteProperty -Name ListURL -Value ($list.ParentWeb.Url + "/" + $list.RootFolder.Url)
Add-Member -InputObject $o -MemberType NoteProperty -Name Title -Value $list.Title
Add-Member -InputObject $o -MemberType NoteProperty -Name Description -Value $list.Description
Add-Member -InputObject $o -MemberType NoteProperty -Name ItemCount -Value $list.ItemCount
# add object to $list global array
$lists += $o
}
$web.Dispose()
}
$site.Dispose()
}
}
}
#export array to csv
$lists | Export-Csv D:\Logs\large_lists.csv -NoTypeInformation -Force
#connect to SharePoint Site and List
$s = New-Object Microsoft.SharePoint.SPSite($reportSiteUrl)
$w = $s.openweb()
$l = $w.GetList($reportListUrl)
#clear SharePoint List
$query = New-Object Microsoft.SharePoint.SPQuery
$query.ViewAttributes = "Scope='Recursive'"
$query.Query = ""
$items = $l.GetItems($query)
$items | % { $l.GetItemById($_.Id).Delete() }
#export to SharePoint List
$lists | ForEach{
$item = $l.Items.Add()
$item["Title"] = $_.Title
$item["SiteCollectionUrl"] = $_.SiteCollectionUrl
$u = New-Object Microsoft.SharePoint.SPFieldUrlValue
$u.Description = "Link"
$u.Url = $_.ListURL
$item["URL"] = $u
$item["Description"] = $_.Description
$item["Count"] = $_.ItemCount
$item.Update()
}
$w.Dispose()
$s.Dispose()
#stop timer and log event
$sw.Stop()
C:\_scripts\sp_log.ps1 -jobName $jobName -message "Reported large lists on SharePoint Farm." -type "Success" -duration $sw.Elapsed.Seconds -linkTitle "Link" -linkUrl "http://my-site.gov/sites/applications/reporting/Lists/Large%20Lists/"
}
#catch exceptions
trap [Exception]{
C:\_scripts\sp_log.ps1 -jobName $jobName -message $_.Exception.Message -type "Error" -duration $sw.Elapsed.Seconds -linkTitle "Link" -linkUrl "http://my-site.gov/sites/applications/reporting/Lists/Large%20Lists/"
}
Get-LargeLists
Решение
Я выполнил сценарий PowerShell, чтобы удалить каждый элемент, и запустил SQL Profiler, чтобы выяснить это. proc_DeleteRecycleBinItem выполняется, что затрагивает несколько таблиц, поэтому мы будем придерживаться запланированного сценария PowerShell, который будет запускаться и создавать отчеты каждые N минут.