SPQuery 适用于列表视图阈值以下的库,但不能超过列表视图阈值
-
10-12-2019 - |
题
因此,我正在构建一个 Web 部件,它枚举当前 Web 中的所有 doclib,抓取所有签出的文件并将它们列在表中,允许用户应用一些所需的元数据并一次签入许多文件 (50)。
此 Web 部件必须在超过列表视图阈值(当前在生产中设置为 15,000 个)的列表上运行,并且还必须在非常大的网站(50,000 - 100,000 个以上文档)上运行。
我在这里遵循处理大型列表的 MS 最佳实践: http://msdn.microsoft.com/en-us/library/ee557257.aspx
使用 SPquery(根本没有定义 CAML),检索 2,000 个项目的页面并以这种方式进行解析。这样做的问题是,Web 部件实际上导致那些非常大(50k+)的网站发生超时。所以我试图让我的 CAML 变得更聪明,只提取已签出的项目:
spQuery.Query = "<Where><IsNotNull>
<FieldRef Name=\"CheckoutUser\" LookupId=\"TRUE\"/>
</IsNotNull></Where>";
spQuery.RowLimit = 2000;
spQuery.ViewAttributes = "Scope=\"Recursive\"";
我正在使用一个 CrossListQueryInfo
query 使用同一个 caml 查询整个网络,当 LVT 上没有列表时,它的工作效果非常好。如果是,我会捕获该异常,并在每个单独的库上使用“较慢”的 SPQuery 重试。
从我读到的所有内容来看,只要我的 CAML 返回的项目少于 LVT,它就应该有效。但是使用上面的CAML会导致错误 The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator
当 SPList.GetItems(spQuery)
叫做。由于我将 rowlimit 设置为 2,000,难道这种情况永远不会发生吗?MS 建议在根本没有定义 CAML 的情况下执行 SPQuery - 基本上从库中获取 2,000 页的所有项目。所以我无法理解为什么我的 CAML 仅在超过视图阈值的列表上失败。
编辑:经过进一步研究,我正在尝试利用 ContentIterator
类来满足我的需求(http://msdn.microsoft.com/en-us/library/microsoft.office.server.utilities.contentiterator.aspx)。使用这篇文章中的示例: http://extreme-sharepoint.com/2012/07/17/data-access-via-caml-queries/
我仍然在内容迭代器上失败,并出现相同的 LVT 错误。
是否需要在我们要执行此查询的每个列表上对“CheckoutUser”字段建立索引?
更新2:这归结为“CheckoutUser”字段未建立索引,并尝试对其进行查询。不幸的是,我们无法在场中的每个图书馆上强制执行此索引。我相信此时我唯一的选择是在非常大的站点上实施某种分页方案来批量处理项目。
最终更新:作为解决方案,我决定强制对库的“CheckoutUser”列建立索引。这应该会极大地提高 Web 部件的整体性能,并允许支持非常大的网站。部署后会立即出现一些头痛,因为我们需要手动设置列表上超过列表视图阈值的列索引,但从长远来看,这将是最好的。
解决方案
我对列表视图阈值如何工作的理解是有限的,但是,我怀疑您的 CAML 查询失败的原因是因为它正在对非索引字段进行过滤,并且 RowLimit 是在“之后”应用的。
我认为对 CheckoutUser 字段建立索引可以解决您的问题,但是听起来您有很多网站。
请允许我建议另一种方法 - 分页。由于每个列表上的 ID 列都已建立索引,因此请实现一个 CAML 查询,其中首先(非常重要)在小于 2000 的 ID 列上进行过滤,然后在 CheckoutUser 字段上进行过滤。如果该查询未返回所需的结果数,则将 2000 增加到 4000 并重复。
我自己没有实现这个解决方案,这只是一个想法。
其他提示
如果您正在查询大型列表,则绝对应该为您正在查询的字段建立索引。不会发生限制,因为索引字段存储在数据库中的单独表中。
我认为我的这篇博文应该有一些帮助:http://vrdmn.blogspot.in/2012/11/sharepoint-list-indexes-under-hood.html