none
Sharepoint 2010/2013 логика работы приложения, в части обращения к СУБД, в случае когда список имеет большое кол-во уникальных разрешений RRS feed

  • Вопрос

  • Добрый день.

    Есть список на SharePoint 2010. В списке более 30.000 элементов.

    В списке есть разрешения: группы пользователей и пользователи,с определенным уровнями разрешений.

    После создания элемента в списке, для элемента запускается рабочий процесс, который прекращает наследование прав от списка. 

    Как следствие, имеем кол-во уникальных разрешений на спике ~= кол-во элементов, т.е. более 30.000, естественно производительность списка деградировала и продолжает деградировать. :(

    В интернете нашел информацию(уже не вспомню где именно) о том, что при превышении порогового значения уникальных разрешений = 5.000, меняется логика работы с СУБД, а именно меняются запросы к СУБД.

    Логи фермы SharePoint + трассировки на СУБД показывают, что происходит большое кол-во операций INSERT,  пример:

    DECLARE @_scopeTbl TABLE(_listId uniqueidentifier NOT NULL,_id uniqueidentifier NOT NULL,_level bit NOT NULL,PRIMARY KEY CLUSTERED(_listId,_id,_level)); 

    DECLARE @_count0_0 INT; 
    SET @_count0_0 = 0; 
    WHILE @_count0_0<@I12P BEGIN  INSERT INTO @_scopeTbl VALUES (@L4, CAST(SUBSTRING(@L13IMG,@_count0_0*16 + 1, 16) AS uniqueidentifier),0); 
    SET @_count0_0=@_count0_0 + 1; 
    END; 

    Где:

    @I12P - кол-во уникальных разрешений списка.

    @L4 - идентификатор списка.

    Получается более 30.000 инсертов в БД.

    Плюс еще несколько подобных инсертов, для списков из которых происходят подстановки в поля списка, и почему то, эти инсерты выполняются дважды, для списка с большим кол-вом уникальных разрешений. В начале, при объявлении переменной "_scopeTbl" и после выполенения подобных инсертов для списков, из которых подставляются значения.

    После всех инсертов, выполняется запрос, вида:

    SELECT t1.[Type] AS c0, UserData.[datetime1], UserData.[nvarchar10], t1.[LeafName] AS c6c8, t9.[nvarchar1] AS c26c27, t9.[nvarchar6] AS c26c30, t10.[tp_ID] AS c32c28, t10.[tp_Created] AS c32c31, UserData.[tp_ItemOrder], UserData.[tp_Created], UserData.[tp_ModerationStatus], UserData.[nvarchar1], UserData.[nvarchar6], t2.[tp_ID] AS c6c16, UserData.[tp_WorkflowInstanceID], t1.[ProgId] AS c36, t1.[MetaInfo] AS c3, UserData.[ntext1], t1.[TimeCreated] AS c6c11, UserData.[float1], UserData.[int2], UserData.[nvarchar19], UserData.[tp_ID], UserData.[nvarchar5], t2.[nvarchar2] AS c6c14, UserData.[bit1], UserData.[tp_GUID], t1.[TimeLastModified] AS c34, t1.[SortBehavior] AS c1, UserData.[tp_Author], UserData.[tp_Editor], UserData.[int1], UserData.[nvarchar13], UserData.[nvarchar18], t9.[tp_ID] AS c26c28, t10.[nvarchar4] AS c32c29, UserData.[tp_ContentTypeId], t2.[tp_Created] AS c6c17, t3.[nvarchar1] AS c18c19, t9.[tp_Created] AS c26c31, UserData.[tp_WorkflowVersion], t1.[LeafName] AS c9, t1.[ItemChildCount] AS c37, UserData.[tp_Version], t1.[Id] AS c4, UserData.[nvarchar4], UserData.[nvarchar9], UserData.[tp_IsCurrentVersion], UserData.[tp_HasCopyDestinations], UserData.[tp_Level], UserData.[datetime3], UserData.[nvarchar12], t10.[nvarchar1] AS c32c27, t2.[nvarchar1] AS c6c7, t8.[Status1] AS c25c21, t10.[nvarchar6] AS c32c30, UserData.[tp_HasAttachment], t1.[ClientId] AS c35, UserData.[tp_Modified], CASE WHEN DATALENGTH(t1.DirName) = 0 THEN t1.LeafName WHEN DATALENGTH(t1.LeafName) = 0 THEN t1.DirName ELSE t1.DirName + N'/' + t1.LeafName END  AS c2, UserData.[nvarchar8], t1.[Type] AS c6c10, t2.[tp_ContentTypeId] AS c6c15, UserData.[nvarchar3], t6.[Status1] AS c23c21, t7.[Status1] AS c24c21, UserData.[tp_UIVersion], UserData.[tp_CopySource], UserData.[datetime2], UserData.[nvarchar11], t5.[Status1] AS c22c21, t9.[nvarchar4] AS c26c29, UserData.[tp_InstanceID], t4.[Status1] AS c20c21, UserData.[tp_UIVersionString], t1.[TimeCreated] AS c12, t1.[FolderChildCount] AS c38, t1.[ScopeId] AS c5, UserData.[nvarchar2], UserData.[nvarchar7], CASE WHEN DATALENGTH(t1.DirName) = 0 THEN t1.LeafName WHEN DATALENGTH(t1.LeafName) = 0 THEN t1.DirName ELSE t1.DirName + N'/' + t1.LeafName END  AS c6c13, t1.[DirName] AS c33, UserData.[nvarchar15] FROM AllUserData AS UserData WITH(INDEX=AllUserData_PK) INNER JOIN Docs AS t1 WITH(NOLOCK) ON (UserData.[tp_RowOrdinal] = 0) AND (t1.SiteId=UserData.tp_SiteId) AND (t1.SiteId = @SITEID) AND (t1.ParentId = UserData.tp_ParentId) AND (t1.Id = UserData.tp_DocId) AND ( (UserData.tp_Level = 1 OR UserData.tp_Level =  2) ) AND (t1.Level = UserData.tp_Level) AND ((UserData.tp_Level = 255 AND t1.LTCheckoutUserId =@IU OR (UserData.tp_Level = 1 AND (UserData.tp_DraftOwnerId IS NULL OR  (UserData.tp_DraftOwnerId <>@IU AND t1.ScopeId NOT IN (SELECT CAST(val AS uniqueidentifier) AS InValues FROM dbo.fn_UnpackCsvString(@L3TXP) ))) OR UserData.tp_Level = 2 AND (UserData.tp_DraftOwnerId = @IU OR t1.ScopeId IN (SELECT CAST(val AS uniqueidentifier) AS InValues FROM dbo.fn_UnpackCsvString(@L3TXP) )))AND (t1.LTCheckoutUserId IS NULL OR t1.LTCheckoutUserId <> @IU ))) AND (UserData.tp_ListId = @L4) AND (UserData.[tp_ListID] =@LISTID) AND (UserData.[tp_CalculatedVersion] = 0 ) AND (UserData.[tp_IsCurrentVersion] = CONVERT(bit,1) ) AND (UserData.[tp_DeleteTransactionId] = 0x ) LEFT OUTER LOOP JOIN AllUserData AS t2 WITH(NOLOCK,INDEX=AllUserData_PK) ON (UserData.[int1]=t2.[tp_ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t2.[tp_RowOrdinal] = 0) AND ( (t2.tp_Level = 1) ) AND (t2.[tp_IsCurrentVersion] = CONVERT(bit,1) ) AND (t2.[tp_CalculatedVersion] = 0 ) AND (t2.[tp_DeleteTransactionId] = 0x ) AND (t2.tp_ListId = @L5) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN AllUserData AS t3 WITH(NOLOCK,INDEX=AllUserData_PK) ON (UserData.[int2]=t3.[tp_ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t3.[tp_RowOrdinal] = 0) AND ( (t3.tp_Level = 1) ) AND (t3.[tp_IsCurrentVersion] = CONVERT(bit,1) ) AND (t3.[tp_CalculatedVersion] = 0 ) AND (t3.[tp_DeleteTransactionId] = 0x ) AND (t3.tp_ListId = @L6) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN Workflow AS t4 WITH(NOLOCK) ON ( CAST ( CAST (UserData.[nvarchar13]AS VARBINARY) AS UNIQUEIDENTIFIER)=t4.[ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t4.SiteId = @SITEID) AND (t4.WebId = @WEBID) AND (t4.ListId = UserData.tp_ListId) AND (t4.ItemId = UserData.tp_Id) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN Workflow AS t5 WITH(NOLOCK) ON ( CAST ( CAST (UserData.[nvarchar15]AS VARBINARY) AS UNIQUEIDENTIFIER)=t5.[ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t5.SiteId = @SITEID) AND (t5.WebId = @WEBID) AND (t5.ListId = UserData.tp_ListId) AND (t5.ItemId = UserData.tp_Id) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN Workflow AS t6 WITH(NOLOCK) ON ( CAST ( CAST (UserData.[nvarchar18]AS VARBINARY) AS UNIQUEIDENTIFIER)=t6.[ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t6.SiteId = @SITEID) AND (t6.WebId = @WEBID) AND (t6.ListId = UserData.tp_ListId) AND (t6.ItemId = UserData.tp_Id) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN Workflow AS t7 WITH(NOLOCK) ON ( CAST ( CAST (UserData.[nvarchar19]AS VARBINARY) AS UNIQUEIDENTIFIER)=t7.[ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t7.SiteId = @SITEID) AND (t7.WebId = @WEBID) AND (t7.ListId = UserData.tp_ListId) AND (t7.ItemId = UserData.tp_Id) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN Workflow AS t8 WITH(NOLOCK) ON ( CAST ( CAST (UserData.[nvarchar10]AS VARBINARY) AS UNIQUEIDENTIFIER)=t8.[ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t8.SiteId = @SITEID) AND (t8.WebId = @WEBID) AND (t8.ListId = UserData.tp_ListId) AND (t8.ItemId = UserData.tp_Id) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN AllUserData AS t9 WITH(NOLOCK,INDEX=AllUserData_PK) ON (UserData.[tp_Author]=t9.[tp_ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t9.[tp_RowOrdinal] = 0) AND ( (t9.tp_Level = 1) ) AND (t9.[tp_IsCurrentVersion] = CONVERT(bit,1) ) AND (t9.[tp_CalculatedVersion] = 0 ) AND (t9.[tp_DeleteTransactionId] = 0x ) AND (t9.tp_ListId = @L8) AND (UserData.tp_ListId = @L4) LEFT OUTER LOOP JOIN AllUserData AS t10 WITH(NOLOCK,INDEX=AllUserData_PK) ON (UserData.[tp_Editor]=t10.[tp_ID]) AND (UserData.[tp_RowOrdinal] = 0) AND (t10.[tp_RowOrdinal] = 0) AND ( (t10.tp_Level = 1) ) AND (t10.[tp_IsCurrentVersion] = CONVERT(bit,1) ) AND (t10.[tp_CalculatedVersion] = 0 ) AND (t10.[tp_DeleteTransactionId] = 0x ) AND (t10.tp_ListId = @L8) AND (UserData.tp_ListId = @L4) WHERE (UserData.[tp_CalculatedVersion] = 0 ) AND (UserData.[tp_IsCurrentVersion] = CONVERT(bit,1) ) AND (UserData.[tp_DeleteTransactionId] = 0x ) AND (UserData.tp_ListID=@LISTID) AND ( (UserData.tp_Level = 1 OR UserData.tp_Level =  2)  AND ( UserData.tp_Level= 255 AND UserData.tp_CheckoutUserId = @IU OR  ( UserData.tp_Level  <> 255 AND (UserData.tp_CheckoutUserId IS  NULL  OR UserData.tp_CheckoutUserId <> @IU)))) AND (UserData.tp_RowOrdinal=0) AND ((UserData.[tp_ID] = @II)) ORDER BY UserData.[tp_ID]  ASC  OPTION (FORCE ORDER, MAXDOP 1)

    Вопросы:

    1. Действительно ли меняется логика обращений приложения SP к СУБД при превышении порогового занчения кол-ва уникальных разрешений списка?

    2. Зачем ОНО делает такое кол-во инсертов, при этом не делает оттуда селекты? или всетаки делает?


    20 июля 2016 г. 8:46

Ответы

  • Добрый день.

    на сколько мне известно, логика не зависит от числа элементов списка. 
    запросы могут быть разные в зависимости от прав запрашиваемых элементов

    в свое время сталкивался с проблемой долгой работы SP и долгих запросов в SQL.
    сейчас в своих решениях стараюсь меньше использовать персональные права.

    еще, как правило, часть элементов можно "архивировать" в папки и на папки назначить права группе людей, а персональные права убрать с этих элементов.


    мой блог Немного о SharePoint

    20 июля 2016 г. 9:15
    Модератор

Все ответы

  • Добрый день.

    на сколько мне известно, логика не зависит от числа элементов списка. 
    запросы могут быть разные в зависимости от прав запрашиваемых элементов

    в свое время сталкивался с проблемой долгой работы SP и долгих запросов в SQL.
    сейчас в своих решениях стараюсь меньше использовать персональные права.

    еще, как правило, часть элементов можно "архивировать" в папки и на папки назначить права группе людей, а персональные права убрать с этих элементов.


    мой блог Немного о SharePoint

    20 июля 2016 г. 9:15
    Модератор
  • Добрый день.

    на сколько мне известно, логика не зависит от числа элементов списка. 
    запросы могут быть разные в зависимости от прав запрашиваемых элементов

    в свое время сталкивался с проблемой долгой работы SP и долгих запросов в SQL.
    сейчас в своих решениях стараюсь меньше использовать персональные права.

    еще, как правило, часть элементов можно "архивировать" в папки и на папки назначить права группе людей, а персональные права убрать с этих элементов.


    мой блог Немного о SharePoint

    Решение раскидать все по папкам - логично и понятно. :)

    20 июля 2016 г. 9:19