【问题标题】:SharePoint 5000 Item limitSharePoint 5000 项目限制
【发布时间】:2017-05-08 01:08:16
【问题描述】:

this 文章中,微软解释了为什么有 5000 项限制。但是我什么时候可以访问超过 5000 个项目?

示例: 我有一个包含 50 000 个项目的列表,我执行行限制为 50 的 caml 查询。sharepoint 是锁定数据库还是仅锁定 50 行? sharepoint 如何知道是否应该锁定某些行或整个数据库?还是取决于caml本身?

锁会影响整个场还是仅影响当前列表,因为 sharepoint 没有每个列表都有自己的表?

【问题讨论】:

    标签: sharepoint sharepoint-2013


    【解决方案1】:
    1. 读取大列表中的所有项目

    在 SharePoint 2010 中,当您对大型列表执行 SPQuery 时,您会收到异常“禁止尝试的操作,因为它超出了管理员强制执行的列表视图阈值”。为了避免这种异常并批量读取列表项,我们可以使用 Content Iterator。

    ContentIterator 有很多可用的方法,这里我们讨论一下http://msdn.microsoft.com/en-us/library/ee560760%28v=office.14%29.aspx

    要使用 ContentIterator,请包含 14/ISAPI/ 中可用的 Microsoft.Office.Server.dll 并包含命名空间 Microsoft.Office.Server.Utilities。

    优势: 批量获取列表项,减少负载。 如果索引列条件返回的值多于列表视图阈值,则按批处理。在这种情况下,普通 SPQuery 会失败。 我们可以随时停止批处理。 坏处: 您不能在 SPQuery 条件中包含非索引列。

    //Run as console application
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.SharePoint;
    using Microsoft.Office.Server.Utilities;
    
    namespace ContentIteratorListItemCollBatch
    {
        class Sample
        {
            static int NumberOfBatch = 0, NumberOfItemsRead = 0, NumberOfException = 0;
    
        static void Main(string[] args)
        {
            using (SPSite site = new SPSite("your site url"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.GetList("Lists/LargeList/AllItems.aspx"); //your list url
                    ContentIterator ci = new ContentIterator("Reading All Items");
    
                    SPQuery qry = new SPQuery();
                    qry.QueryThrottleMode = SPQueryThrottleOption.Strict; //Ensuring that all users come under List View Threshold. (Including farm admins / box administrators).
    
                    qry.RowLimit = 2000; //Number of Items read in a batch. But it should be less than List View Threshold.
    
                    qry.Query = qry.Query + ContentIterator.ItemEnumerationOrderByID; //Not Required, Include for faster output.  
                    //Don't use ContentIterator.ItemEnumerationOrderByNVPField, it gets into infinite loop.
    
                    ci.ProcessListItems(list, qry, ProcessItemColl, ProcessErrorColl);
                    Console.WriteLine("\nBatch count: " + NumberOfBatch + "\n\nTotal number of items read: " + NumberOfItemsRead);
                    Console.ReadLine();
                }
            }
        }
    
        static public bool ProcessErrorColl(SPListItemCollection itemColl, Exception e)
        {
            // process the error
            NumberOfException++;
            return true;
        }
        static public void ProcessItemColl(SPListItemCollection itemColl)
        {
            //Work on the ListItem Collection object with your own condition
            //foreach (SPListItem item in itemColl)
            //{
    
            //}
            Console.WriteLine("Number of Items Read: " + itemColl.Count);
            NumberOfBatch++;
            NumberOfItemsRead += itemColl.Count;
        }
    }
    

    }

    我的大列表包含 25,000 项。您可以从输出中看到,它每批 2000 个项目读取 25,000 个项目。

    输出

    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 1000
    
    Batch count: 13
    
    Total number of items read: 25000
    
    1. 有条件地读取大列表中的项目

    确保满足以下条件。 在 where 条件下只允许索引列。 您应该包括 ContentIterator.ItemEnumerationOrderByNVPField。 在下面的代码中,标题是一个索引列。创建自定义列表后,标题将作为索引列。

    //作为控制台应用程序运行

    使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Text; 使用 Microsoft.SharePoint; 使用 Microsoft.Office.Server.Utilities;

    namespace ContentIteratorListItemCollBatch
    {
        class Sample
        {
        static int NumberOfBatch = 0, NumberOfItemsRead = 0, NumberOfException = 0;
    
        static void Main(string[] args)
        {
            using (SPSite site = new SPSite("your site url"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.GetList("Lists/LargeList/AllItems.aspx"); //your list url
                    ContentIterator ci = new ContentIterator("Reading All Items");
    
                    SPQuery qry = new SPQuery();
                    qry.QueryThrottleMode = SPQueryThrottleOption.Strict; //Ensuring that all users come under List View Threshold. (Including farm admins / box administrators).
    
                    qry.RowLimit = 2000; //Number of Items read in a batch. But it should be less than List View Threshold.
    
                    qry.Query = @"<Where><Contains><FieldRef Name='Title' /><Value Type='Text'>9</Value></Contains></Where>";
    
                    qry.Query = qry.Query + ContentIterator.ItemEnumerationOrderByNVPField;
                    //Have to include this line.
    
                    ci.ProcessListItems(list, qry, ProcessItemColl, ProcessErrorColl);
                    Console.WriteLine("\nBatch count: " + NumberOfBatch + "\n\nTotal number of items read: " + NumberOfItemsRead);
                    Console.ReadLine();
                }
            }
        }
    
        static public bool ProcessErrorColl(SPListItemCollection itemColl, Exception e)
        {
            // process the error
            NumberOfException++;
            return true;
        }
        static public void ProcessItemColl(SPListItemCollection itemColl)
        {
            //Work on the ListItem Collection object with your own condition
            //foreach (SPListItem item in itemColl)
            //{
    
            //}
            Console.WriteLine("Number of Items Read: " + itemColl.Count);
            NumberOfBatch++;
            NumberOfItemsRead += itemColl.Count;
        }
    }
    

    }

    在 SPQuery 中,如果索引字段获取的次数超过列表视图阈值限制,它将失败。 ContentIterator 通过批处理来处理它。

    Output
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 2000
    Number of Items Read: 233
    
    Batch count: 5
    
    Total number of items read: 8233
    

    【讨论】:

      【解决方案2】:

      首先,关于“整个农场”的问题 - 您的农场中可以有多个数据库。当您创建新网站集(由SPSite 对象表示的网站集)时,您可以选择一个数据库来存储它。每个数据库都有自己的AllUserData 表。因此,您可以通过查询锁定的最大范围是此表。当然,如果您的所有网站都位于一个数据库中,您可能会锁定所有内容。

      回答第二个问题 - 这很复杂。在某些情况下,您不打算加载超过 5000 行,但计算需要它。 SharePoint 会终止您的查询。 例如,您有一个很大的项目列表。您应用返回少量项目的过滤器。有用。现在,您在某些字段上添加“分组依据”- 繁荣,它不起作用。 此外,例如,默认的“所有项目”视图会出现问题。您可以使用它,因为它以 30 个项目为一组返回项目。但是,如果您想按特定列进行过滤 - 过滤器不起作用,因为它超过了 5000 个限制。

      【讨论】:

      • 我们不使用标准的列表视图,我们构建了一个列表展示的框架。我对 caml 查询感兴趣。什么查询会导致问题?我们永远不会得到超过 50 个项目(行限制)。具有这种行限制的查询也会导致整个数据库锁定吗?为什么我要问:我们有许多包含超过 10k 项的列表,我认为查询一个列表比查询更多(每个 5k 项)要快得多。例如,我们想获得前 50 项,但我们不知道这些项目是否在第一、第二或任何其他列表中。所以我们必须查询所有列表,将它们放入一个集合中,排序并返回前 50 个。
      【解决方案3】:

      当您在网站集中的列表中查询项目时,您有几个选项。

      检索数据最快的方法是索引列表并使用搜索返回项目。您可以自定义排名模型并返回您的前 50 项。缺点是数据只会是您上次抓取时的新鲜数据。

      使用自定义代码的另一个选项是使用带有SPSiteDataQuery 对象的交叉列表查询。

      这将允许您返回不同列表中的前 50 项。

      就查询超过 5000 个限制的大型列表而言,可以通过提高阈值或以管理员身份执行查询来完成,但实际上并不推荐这样做。 You can put indexes on columns 如此大的列表访问速度更快。使用对象模型时,您可以做任何您喜欢的事情,但您可能想要衡量性能影响。从数据的角度来看,SharePoint 中的数据库实际上是一个抽象概念,您应该更多地关注如何以“SharePoint”方式进行操作,而不是 SharePoint 本身如何访问基础数据。

      【讨论】:

        【解决方案4】:

        我有一个包含 20k 条记录的列表,阈值设置为 200k(MS 说 5k)。 我同时测试了 4 个用户点击返回 20 k 记录但分页为每页 30 个项目的列表视图页面。什么都没有。当读取正在进行时,这个 5k 限制是否实际上锁定了整个列表?如果是这样,怎么3个用户可以同时访问同一个listview页面?

        【讨论】:

          【解决方案5】:

          由于您只返回 30 行,因此永远不会达到列表视图阈值。但是,如果您尝试应用 order by,那么为了执行该 orderby,它必须扫描所有 20 k 条记录,尽管只显示了 30 条。所以在这种情况下,阈值就会被触发。

          【讨论】:

            猜你喜欢
            • 2020-05-07
            • 2019-11-30
            • 1970-01-01
            • 2020-12-14
            • 2011-08-30
            • 2020-05-06
            • 2018-08-06
            • 2023-04-07
            • 1970-01-01
            相关资源
            最近更新 更多