- PVSM.RU - https://www.pvsm.ru -
Всем привет!
В этой статье мы решили поделиться своими жизненными наблюдениями за проблемой производительности больших списков в SharePoint.
Итак, мы достаточно часто сталкиваемся с ситуациями, когда есть список на портале SharePoint, в котором хранятся и обрабатываются, например, заявки пользователей. Дополнительно всегда возникает желание сделать так, чтобы все заявки хранились в одном месте, с другой стороны — чтобы права на эти элементы были только у пользователя, подавшего заявку, и у группы или групп пользователей, которые участвуют в ее обработке.
Сначала немного терминологии:
ACL (Access Control List) [1] – упорядоченный список принципалов, которые определяют права на элемент или группу элементов.
Security Scopes [2] – набор пар групп или пользователь + ACL.
Microsoft рекомендует [3] соблюдать достаточно простые правила: избегать количества одновременных Security Scopes более 5 000 на одну библиотеку документов или на один список.
Почему так? Откуда взялось ограничение? Для начала ответим на вопрос, каким образом MS SharePoint обрабатывает запрос к списку.
Такому подходу есть объяснения, и связаны они с поддержкой модели внешних поставщиков членства и ролей в первую очередь (AD, т.е. AD является наиболее широко распространенным поставщиком членства и ролей).
На практике можно видеть, что проблемы начинаются уже с 1000 элементов с уникальными правами.
С помощью этих [4] SQL-запросов можно посчитать, сколько сейчас у вас Security Scopes:
SELECT [SiteId], [ScopeId], [RoleDefWebId], [WebId], [ScopeUrl], [Acl]
FROM [your Content DB].[dbo].[Perms] order by scopeurl
An even better query exposes the web URL
SELECT [fullurl],perms.[SiteId] , perms.[ScopeId], [RoleDefWebId], [WebId], [ScopeUrl], [Acl]
FROM [dbo].[Perms],[dbo].allwebs
where perms.WebId = allwebs.id
order by scopeurl
As an aside, you can see the number of security principals per scope, using this SQL:
select COUNT(ra.PrincipalId) as [Count],p.ScopeUrl from RoleAssignment ra with(nolock)
join Perms p with(nolock)
on p.SiteId = ra.SiteId and p.ScopeId = ra.ScopeId
group by p.ScopeUrl
order by p.ScopeUrl desc
Как Microsoft предлагает решать проблему:
К чему приводит нарушение этих рекомендаций:
Для решений на базе MS SharePoint критически важно, чтобы ферма держала нагрузку, и вот почему.
Для разработчика нет поддержки транзакций. И наборы операций вида (т.е. если создать элемент, разорвать права, выдать на него права в MS SharePoint):
var item = list.AddItem(...);
// ...
item.Update();
item.BreakRoleInheritance(false);
item.RoleAssignments.Add(new SPRoleAssignment(...));
будут прерываться в неожиданных местах, просто потому что ферма не выдерживает нагрузки (т.е. не из-за логических ошибок).
Понятно, что рекомендации 2 и 4 носят более камерный характер и не решают задачу хранения элементов вместе и уникальных прав, поэтому остановимся на первом как самом действенном способе – использование папок.
Для примера возьмем список из реально работающей системы, в которой на текущий момент 132 073 элементов:

В ней 3 590 Security Scopes – выглядит примерно вот так:

Внутри списка 721 папка...:

… на которые выданы права следующим образом:

По данным Google Analytics, среднее время загрузки страницы менее секунды — при уровне посещений именно этого списка за этот период порядка 968 в день, в рабочее время.

В соответствии с нашим подходом права раздаются вот так:
public static void ProcessItem(SPListItem item, SPFolder folder)
{
var file = item.Web.GetFile(item.UniqueId);
// Внимание не используйте item.File т.к. он во многих случаях будет null
// http://msdn.microsoft.com/ru-ru/library/microsoft.sharepoint.splistitem.file.aspx
file.MoveTo(string.Format("{0}/{1}", folder.Url, item[SPBuiltInFieldId.LinkFilename]));
}
Также хочется добавить, что если наборы прав различаются не разрешениями на чтение видимости, а возможностью изменения, можно использовать Event Handler, который будет запрещать изменения.
class PermissionEventHandler : SPItemEventReceiver
{
public override void ItemUpdating(SPItemEventProperties properties)
{
var updatingAllowed = CheckUserHasPermission(properties.Web.CurrentUser, properties.ListItem);
// определить может ли пользователь изменять элемент
if (!updatingAllowed)
{
properties.Cancel = true;
properties.ErrorMessage = "Access denied";
}
}
public override void ItemAdding(SPItemEventProperties properties)
{
//...
}
//...
}
До изобретения этого подхода нам пришлось в течение 5 лет плотно заниматься SharePoint, съесть немало собак и кактусов. У него есть свои нюансы, но он абсолютно точно работает — опробовано уже на двух порталах.
Как всегда, рады были поделиться опытом!
Автор: eastbanctech
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/microsoft/54474
Ссылки в тексте:
[1] ACL (Access Control List): http://technet.microsoft.com/en-us/library/cc962007.aspx
[2] Security Scopes: http://sharingthepoint.blogspot.ru/2010/09/sharepoint-security-model.html
[3] рекомендует: http://technet.microsoft.com/en-us/library/cc262787.aspx
[4] этих: http://reality-tech.com/2012/03/19/clarifying-the-security-scope-limits-in-sharepoint-lists/
[5] Источник: http://habrahabr.ru/post/211735/
Нажмите здесь для печати.