Управление большими списками/библиотеками в SharePoint
В SharePoint 2010 впервые появилось ограничение на количество выбираемых элементов единовременно из списка или библиотеки документов. Ровно такое же ограничение перекочевало в последующие версии SharePoint On-prem и SharePoint Online.
Причина такого ограничения понятна: ограничить нагрузку на систему путем запрета на выполнение ресурсоемких операций. По умолчанию это ограничение равно 5000 элементам для пользователей и 20000 для администраторов/аудиторов.
Как считать
Первое что приходит на ум при взгляде на фразу "не более 5000 элементов" - никакому пользователю никогда и ни при каких обстоятельствах нет необходимости просматривать одновременно такое большое количество элементов. Тем более в представлениях списка есть постраничный выбор и по умолчанию на одной странице выводится всего 30 элементов. Но даже если у вас в представлении количество элементов на странице равно 10, а предел установлен в 10000 (т.е. выборка составляет всего 1% от максимально допустимой) то это не спасает от получения следующего исключения:
Самое важное, что необходимо понимать - механизм расчета, согласно которому запрос данных считается превышающим пороговое значение. Для примера я создал список, содержащий 11К+ записей. Параметры ограничений настроил следующим образом:
- Пороговое значение - 2000 элементов
- Предупреждение - 1200 элементов
Размер страницы в представлениях равен 50, без группировки.
Представление списка
Самый простой пример, с которого мы начнем: представление без фильтра и без сортировки. В этом случае превышение порогового значения не будет сколько элементом не добавляй:
Если представление списка в SharePoint:
- не имеет сортировки;
- не имеет фильтрации;
- размер страницы не превышает пороговое значение.
то данные в этом списке можно просматривать в не зависимости от их количества. Ограничение в этом случае не действует.
Что здесь не так?
В этом случае сообщение об ошибке будет выдано при попытке отсортировать представление:
или отфильтровать его:
В списке много элементов, которые выводятся постранично без фильтрации и сортировки. Но все мы знаем, что при выводе данных постранично обязательно должна быть сортировка. И она есть:
Представление в SharePoint всегда отсортированы. Если параметры сортировки явно не указаны, то данные сортируются по полю ID от меньшего к большему.
Из этого следует, что мы всегда можем сортировать представление по полю ID (в любом направлении) не зависимо от количестве данных и ограничений на выборку. Если в пример выше добавить сортировку по полю ID или выполнить сортировку на форме просмотра представления, то всё будет работать (только фильтровать по полю ID не получится). Если у вас большой список/библиотека и вам необходимо сортировать по дате создания (выводить новые элементы, документы сверху), то используйте сортировку по полю ID в обратном порядке.
Индексированные поля
Чтобы представление с большим количеством элементов можно было сортировать, то эти поля должны быть добавлены в список индексируемых. В SharePoint 2016 это происходит автоматически, в предыдущих версиях придется делать это вручную. Индекс в SharePoint работает следующим образом:
Для индексируемого поля в таблице dbo.NameValuePair_{COLLATION} создаются записи, содержащие значения поля для каждого элемента списка:
В дальнейшем эти данные используются при выборке данных из списка.
Иногда говорят, что поле ID всегда автоматически индексируемое. Это не так, совсем не так. Поле ID не может быть добавлено в список индексируемых, т.к. значения этого поля всегда уникальны и нет никакого смысла создавать дубликат этих значений.
Таким образом:
Представления в SharePoint всегда можно сортировать по полю ID. Для сортировки больших списков по другим полям, эти поля необходимо добавить в список индексируемых.
Также необходимо помнить о том, что значения в индексе создаются/изменяются/удаляются при соответствующих операциях в списке, что снижает производительность.
Фильтрация
Фильтрация больших списков аналогична сортировке - нельзя фильтровать по неиндексированным полям. Даже если результат запроса всегда пустой:
Фильтрация больших списков возможно только по индексированным полям.
Обход ограничения
Самый простой способ - увеличить максимальное значение выбираемых элементов в свойствах веб-приложения:
Либо с помощью PowerShell:
$app = Get-SPWebApplication -Identity https://portal.company.ru
$app.MaxItemsPerThrottledOperation = 10000
$app.Update();
Помимо этого можно отключить проверку на превышение лимита для конкретного списка. Через PowerShellб используя свойство SPList.EnableThrottling:
$web = Get-SPWeb http://portal.company.ru
$list = $web.GetList("Lists/MyMegaList")
$list.EnableThrottling = $false
$list.Update();
Последний вариант более предпочтителен, т.к. позволяет контролировать большие списки, явно указывая к каким из них не относится ограничение.
Также можно распределить содержимое списка/библиотеки по папкам.