none
Probleme lors de l'execution d'une requete - A l’éxécution <Mémoire insuffisante> RRS feed

  • Question

  • Bonjour,

    J'ai un soucis sur SharePoint 2013 :

    J’utilise l’objet SPQuery pour exécuter une requete sur mon site

    Cet objet SPQuery a une propriété Query qui est le texte (chaine de caractères) de la requete a éxécuter. C’est du CAML

    Pour matcher les documents a afficher selon la bibliothèque où l’on se trouve je dois utiliser le statement <In> (équivalent du include en SQL) pour mes 2900 bibliothèques.

    Le statement <In> est limité à 500 entrées, je dois donc imbriquer les statements dans des conditions <Or> par groupe de 500 soit 6 <In> de 500 Values (correspondent à mes bibliothèques).

    La structure CAML est donc :

    <Or>

        <In></In>

        <Or>

            <In></In>

            <Or>

                <In></In>

                    <Or>

                        <In></In>

                        <In></In>

                   </Or>

            </Or>

        </Or>

    </Or>

    A l’éxécution , j'obtiens le message : <Mémoire insuffisante>   

    Quelqu'un pourrait-il me dire ce que je dois faire pour pouvoir executer cette requete sans erreur ?


    Jay

    lundi 29 septembre 2014 10:39

Réponses

  • Merci pour votre aide pendant ces quelques jours.

    Finalement, j'ai trouvé la solution à mon problème: J'effectue la requête sans tenir compte des bibliothèques (donc pas de <In> imbriqués qui font planter la requête) et j'itère le résultat pour tester la présence des documents dans les bibliothèques en LINQ. Ca fonctionne très bien, les performances sont au rendez-vous et la requête ne risque plus de mettre en péril les performances du SharePoint dû aux accès concurrentiels.


    Jay

    jeudi 2 octobre 2014 09:26

Toutes les réponses

  • Bonjour

    Pouvez nous eclairer sur le scenario fonctionel pour mieux comprendre ce que vous tentez de faire ?

    Parceque à part ajouter de la RAM sur le serveur là on peut pas vous proposez beaucoup plus de choix ;)

    Par contre peut etre que réorganisation du process en amont, ou la creation d'un index ou autre pourrait répondre à votre besoin, mais là moi j'ai pas compris ! :)


    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

    lundi 29 septembre 2014 12:03
  • Bonjour,

    Fonctionnellement, je dois afficher des documents qui sont présents dans des bibliothèques (sorte de conteneur / dossier, pas bibliothèque au sens SP) que je désire visualiser.

    Techniquement, dans ma bibliothèque de documents, j'ai ajouté une colonne de type Recherche qui pointe sur ma liste "Bibliothèque" (sur le champ Guid) acceptant les multi valeurs. De ce fait, chaque document peut être publié dans une ou plusieurs bibliothèque (dossier virtuel, pas bibliothèque au sens SP). Cette liste "Bibliothèque", pour faire simple, a un champ Guid (valeur ToString d'un Guid .NET) et un libellé. Les éléments représentent mes dossiers. Il y a aujourd'hui près de 3000 éléments.

    Il est, donc, tout naturel que ma requête CAML comporte un <In> pour déterminer les documents à remonter à partir des bibliothèques spécifiées en paramètres. Etant donné que le statement <In> est limité à 500 valeurs, je dois imbriquer les <In> à l'aide de <And> par groupe de 500 sauf qu'au delà de certain nombre, le message <Mémoire insuffisante> apparait.

    Voici la pseudo requête que je tente d'effectuer:

    <Where>

        <In>500 valeurs Guid de bibliothèque</In>

        <And>

            <In>500 valeurs Guid de bibliothèque</In>

            <And>

                <In>500 valeurs Guid de bibliothèque</In>

                <And>

                    <In>500 valeurs Guid de bibliothèque</In>

                    <And>

                        <In>500 valeurs Guid de bibliothèque</In>

                        <In>500 valeurs Guid de bibliothèque</In>

                    </And>

                </And>

            </And>

        </And>

    </Where>

    J'ai le message d'erreur à partir du moment où un 5 <In> est nécessaire (à partir du moment où j'ai plus de 2000 guid en paramètre).

    J'espère avoir été assez clair!

    Dans l'attente de votre réponse,

    Cordialement


    Jay

    lundi 29 septembre 2014 12:55
  • Bonjour

    merci pour les précisions

    Ceci dit je ne comprends pas pourquoi vous rechercher les documents associés à l'ensemble de vos "bibliothèques" en y passant plus de 2000 guids en parametres... L'idée n'est pas d'afficher les documents associés à une bibliothèque donnée ? ou alors j'ai rien compris ! :)

    Je reformule au cas où :

    • vous avez une notion de "bibliothèque" métier qui est virtuelle, elle a juste un nom et un GUID
    • Vous stockez "physiquement" des fichiers dans 1 doc lib du sharepoint et associez les fichiers à 1 à N "bibliothèque métier" par le biais d'unne colonne de type lookup (recherche) à valeurs multiples (le même doc peut etre associé à plusieurs libs)

    Ensuite c'est là où  j'ai un doute sur ma compréhension : 

    • vous cherchez à faire l'affichage d'une bibliothèque métier, donc il y a un seul GUID en entrée pour moi, il faut juste récupérer l'ensemble des docs dont le lookup contient ce guid
    • ou vous cherchez à savoir pour un doc physique à quelles "bibliothèque métier" il est associé, et pour ça il suffit du'iliser le(s) GUID présent dans le loockup et requetter sur la liste de référence de ces bibliothèque

    Quelque soit l'option je vois pas où on aurait besoin de renseigner plus de 2000 GUID :)


    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

    lundi 29 septembre 2014 13:18
  • Je reformule au cas où :

    • vous avez une notion de "bibliothèque" métier qui est virtuelle, elle a juste un nom et un GUID
    • Vous stockez "physiquement" des fichiers dans 1 doc lib du sharepoint et associez les fichiers à 1 à N "bibliothèque métier" par le biais d'unne colonne de type lookup (recherche) à valeurs multiples (le même doc peut etre associé à plusieurs libs)

    C'est exactement ça!

    Sauf que les bibliothèques ont une notion hiérarchique (liste "Bibliothèques" colonne "Parent" de type lookup sur elle-même sur la colonne Guid), à savoir:

    - Bibliothèque 1

      - Bibliothèque 1.1

        - Bibliothèque 1.1.1

        - Bibliothèque 1.1.2

        - Bibliothèque 1.1.3

          - Bibliothèque 1.1.3.1 (etc..)

    - Bibliothèque 2

      - Bibliothèque 2.1 (etc..)


    Fonctionnellement, lorsque je suis sur le menu "Bibliothèque 1", il me faut visualiser les documents qui appartiennent à la bibliothèque 1 et à toute sa descendance, soit, les bibliothèques 1.1, 1.1.1, 1.1.2, 1.1.3, 1.1.3.1 etc... Si en revanche, je suis positionné sur la bibliothèque 1.1.3, je ne verrai que les documents de la bibliothèque 1.1.3 et sa descendance, soit 1.1.3.1 etc...

    Plus on se trouve haut dans la hiérarchie, plus j'ai de bibliothèques potentielles à prendre en compte. Il m'arrive, donc, par endroit, d'être à plus de 2000 bibliothèques à spécifier.

    N'y-a-t-il pas une clé de configuration pour une taille maximale de requête ou autre qui empêche ma requête de tourner? Car fonctionnellement et côté algorithme tout semble OK!


    Jay

    lundi 29 septembre 2014 13:37
  • Bon c'est plus clair !

    N'y-a-t-il pas une clé de configuration pour une taille maximale de requête ou autre qui empêche ma requête de tourner? Car fonctionnellement et côté algorithme tout semble OK!

    Sans doute en jouant sur les threshold côté Central Admin ça peut jouer... bien que j'en doute, mais ce type d'approche me semble mauvaise et ressemble plus à une solution de facilité plutôt que d'efficacité ! vous cherchez à permettre à votre serveur de traiter une requête qui va faire ramer votre infra. Imaginez si 50 utilisateurs exécutent la même requête (ou du même acabit) en même temps ! A mon sens il y a un pbm sur l'approche.

    J'aurais plutôt tendance à rajouter une colonne sur vos docs, type lookup multiple, pointant aussi sur la liste des "bibliothèque metier" que j’alimenterai automatiquement par un code déclenché via EventReceiver, voir TimeJob qui serait chargé d'aalyser pour chaque doc et leur association actuelle de "bibliothèque métier" et de déterminer qu'elles relations "implicites" cela donne avec les potentielles bibliothèque métier parentes. Ainsi vous auriez un champs contenant toutes les refs à toute les bibliothèque liée à la "branche" et cela vous permettrez de requeter sur ce champ en disant "donne moi les doc où on trouve LE guid de cette bibliothèque metier sur ce second champ". En gros un pré calcul qui soulagera votre infra et assurera un temps constant d'affichage à vos end users !


    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

    lundi 29 septembre 2014 13:55
  • J'aurais plutôt tendance à rajouter une colonne sur vos docs, type lookup multiple, pointant aussi sur la liste des "bibliothèque metier" que j’alimenterai automatiquement par un code déclenché via EventReceiver, voir TimeJob qui serait chargé d'aalyser pour chaque doc et leur association actuelle de "bibliothèque métier" et de déterminer qu'elles relations "implicites" cela donne avec les potentielles bibliothèque métier parentes.

    Bonjour,

    Ce que vous me préconisez n'est pas possible car cela signifierait que les documents soient potentiellement affectés à la totalité des bibliothèques (s'ils sont publiés sur tous les bouts de branches), ce qui n'est pas autorisé par le champ de type recherche multi valeurs (limitation du nombre de valeurs sur un lookupvaluecollection). Sinon, il faut s'orienter sur une autre liste SP qui servirait de "table de correspondance" entre un ID de document et Guid de bibliothèque. Si l'affectation est trouvée, le document est affiché... Mais à ce jour cela peut représenter 11000 docs * 3000 bibliothèques. Cela fait beaucoup pour une liste SP...

    Dans l'attente de votre retour,

    Cordialement


    Jay

    mardi 30 septembre 2014 09:40
  • J'aurais plutôt tendance à rajouter une colonne sur vos docs, type lookup multiple, pointant aussi sur la liste des "bibliothèque metier" que j’alimenterai automatiquement par un code déclenché via EventReceiver, voir TimeJob qui serait chargé d'aalyser pour chaque doc et leur association actuelle de "bibliothèque métier" et de déterminer qu'elles relations "implicites" cela donne avec les potentielles bibliothèque métier parentes.

    Bonjour,

    Ce que vous me préconisez n'est pas possible car cela signifierait que les documents soient potentiellement affectés à la totalité des bibliothèques (s'ils sont publiés sur tous les bouts de branches), ce qui n'est pas autorisé par le champ de type recherche multi valeurs (limitation du nombre de valeurs sur un lookupvaluecollection). Sinon, il faut s'orienter sur une autre liste SP qui servirait de "table de correspondance" entre un ID de document et Guid de bibliothèque. Si l'affectation est trouvée, le document est affiché... Mais à ce jour cela peut représenter 11000 docs * 3000 bibliothèques. Cela fait beaucoup pour une liste SP...

    Dans l'attente de votre retour,

    Cordialement


    Jay

    Ce que j'ai oublié de vous préciser, c'est que de plus, je ne peux pas mettre en place cette solution car chaque utilisateur a menu "différent" composé de bibliothèques et sous bibliothèques qu'il a le droit de voir ou non.

    Pour schématiser et en partant du principe d'un "menu" (bibliothèques) tel que:

    - Bib A

      - Bib A.1

        - Bib A.1.2

        - Bib A.1.3

      - Bib A.2

        - Bib A.2.2

        - Bib A.2.3

    - Bib B

      - Bib B.1

        - Bib B.1.2

    1 document est publié dans la bibliothèque "Bib A.2.2", la colonne lookup pré calculée vaudra "Bib A.2.2;Bib A.2;Bib A", ok!

    1 utilisateur qui a accès à toutes les bibliothèques et clique sur "Bib A.2.2" ou "Bib A.2" ou "Bib A" verra le document s'afficher, ok!

    Mais 1 utilisateur qui n'a accès qu'à "Bib A.2" et "Bib A" NE pourra PAS visualiser le document car il a été publié dans une sous bibliothèque qu'il n'a pas le droit de visualiser.

    La notion des bibliothèques ne peut pas être portée par les documents.


    Jay

    mardi 30 septembre 2014 10:12
  • Bonjour

    On est d'accord sur plutôt une liste de correspondance, et même effectivement vu le nb potentiel de références, vous serez hors limites....

    Plus je comprends votre besoin, moins je comprends l'utilisation de SharePoint dans votre contexte. Vous n'utilisez pas les vues sur des listes de documents, vous n'allez pas utiliser les permissions car apparemment votre bibliotheque metier porte son propre systèmes de droits ?, manifestement aucune meta données utilisée ? Et comment comptez vous exploiter les resultats du moteur de recherche si quelqu'un accède à celui si pour chercher un document ?

    A ce propos cela pourrai etre une option d'utiliser l'API du moteur de recherche pour retrouver vos documents liés à une bibliothèque données et par code "parser" l'id de la bibliothèque pour determiner à la volée les ids de bibliotheques parentes...

    Sinon je pense sincerement que votre système est tellement spécifique que vous avez tout autant interet à stocker toutes ces infos (correspondance document / lib metier / permissions) dans une base SQL dédiée et utiliser et requeter directement ds ce sql depuis vos pages/webpart


    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

    mardi 30 septembre 2014 11:26
  • Plus je comprends votre besoin, moins je comprends l'utilisation de SharePoint dans votre contexte. Vous n'utilisez pas les vues sur des listes de documents, vous n'allez pas utiliser les permissions car apparemment votre bibliotheque metier porte son propre systèmes de droits ?, manifestement aucune meta données utilisée ? Et comment comptez vous exploiter les resultats du moteur de recherche si quelqu'un accède à celui si pour chercher un document ?

    Le choix s'est orienté sur SharePoint uniquement (en très grande partie) pour son moteur de recherche... (surtout la notion de recherche à l'intérieur des documents .pdf, .word...) Effectivement, pour le reste, une simple appli asp.net aurait fait l'affaire mais là n'est pas la question puisqu'il s'agit de SharePoint ici :)

    Même le moteur de recherche n'est plus en standard et j'ai dû développer un webpart de recherche qui utilise les objets SearchExecutor et KeywordQuery pour passer dans le goulot de recherche de SharePoint. Je récupère ensuite les documents pour les repasser dans la moulinette des droits spécifiques pour son affichage ou non.

    Sinon, la solution d'une base déportée ne me semble pas une mauvaise idée même si je trouve cela moins "propre" que de tout avoir centralisé sur SP. Quand vous me faite part de votre interrogation de l'utilisation de SP dans le contexte, à l'inverse, je ne pensais pas que SP pouvait faire moins bien qu'un site asp.net standard à partir du moment où l'on met les mains dans le spécifique et je trouve cela regrettable. Pourquoi tant de limitations/contraintes alors que nous savons qu'il s'agit de SQL et IIS derrière?

    Sinon, temporairement, avez-vous une idée sur la/les "clés de configuration" (taille requête/threshold) à modifier pour que la requête puisse être exécutée même si les performances ne seront pas au rendez-vous?


    Jay

    mardi 30 septembre 2014 11:47
  • Bon on vas pas rentrer dans le débat qui pourrai etre long de savoir quand SharePoint est une bonne base de départ pour une appli metier et quand il ne l'est pas :) Cela depends de bien trop de critères ! Je suis d'accord avec vous sur le fond, mais l’expérience sur SharePoint fait aussi dire qu'il faut éviter de trop le "tordre" pour garder quelque chose de maintenable et performant. N'oubliez pas non plus que la partie GED est une des multiples briques de ce produit, qui de fait est un moteur "générique". Ceci implique un coût sur la performance forcement par rapport à un code purement spécifique à un besoin particulier. Pour finir sur ce sujet, certes SharePoint repose sur SQL Server, mais une liste SharePoint n'est pas une table sql non plus ! :)

    Pour etre plus pragmatique, si vous êtes déjà "à fond" ;) dans les meandres de l'API de search, j'aurais tendance à dire que cela devrait vous permettre de retrouver les bibliotheque metier (toute la hierarchie de la branche) à travers l'index et de n'utiliser votre moulinette que pour le filtres des permissions custom. 

    Je m'explique:

    • le end user souhaite consulter la lib metier 2.3.5
    • vous faite une première requete de search pour trouver tous les doc ayant la méta "lib metier" = "2.3.5"
    • ensuite en recursif les requetes pour "remonter" dans la hierarchie : tous les doc ayant la méta "lib metier" = 2.3, puis = 2

    En gros cela reviendrai à utiliser le moteur de recherche à la place 'une base métier sql;)

    Et bien sûr cela marche uniquement si on peut simplement utiliser la nomenclature des lib metier associées pour retrouver la hierarchie :(

    un dernier point sur le coté "propre" : si vous partez sur plus de 30 millions de lignes, mettre ça dans une liste SharePoint ça ne sera pas propre non plus c'est clair ! :) la limite est plutot à 2 millions par listes. Donc la base métier "à côté" c'est plutot propre finalement. Vu la volumétrie et la composante "permissions" je me demande même si un cube serait pas approprié pour "pré calculer" l'ensemble des documents dispos pour l'ensemble des end users :)

    Pour finir, les threshold, ça ce passe dans le site admin central / gestion des applis web. Vous selectionnez l'appli web qui va bien, et dans le ruban, bouton general settings, avec la petit fleche vers le bas il y a un menu "limites" :

     

    sinon la doc à ce sujet est ici : http://technet.microsoft.com/fr-fr/library/cc262787(v=office.15).aspx


    Blog Sharepoint : www.paslatek.net Twitter : @LimozinLionel

    mardi 30 septembre 2014 12:29
  • Merci pour votre aide pendant ces quelques jours.

    Finalement, j'ai trouvé la solution à mon problème: J'effectue la requête sans tenir compte des bibliothèques (donc pas de <In> imbriqués qui font planter la requête) et j'itère le résultat pour tester la présence des documents dans les bibliothèques en LINQ. Ca fonctionne très bien, les performances sont au rendez-vous et la requête ne risque plus de mettre en péril les performances du SharePoint dû aux accès concurrentiels.


    Jay

    jeudi 2 octobre 2014 09:26