Dela via


OData Analytics-frågeriktlinjer för Azure DevOps

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019

Tilläggsutvecklare kan dra nytta av att följa riktlinjerna i den här artikeln för att utforma effektiva OData-frågor mot Analytics för Azure DevOps. Genom att följa dessa riktlinjer ser du till att frågorna har bra prestanda för körningstid och resursförbrukning. Frågor som inte följer dessa riktlinjer kan leda till dåliga prestanda, långa rapportväntetider, frågor som överskrider tillåten resursförbrukning eller tjänstblockeringar.

Kommentar

Analytics-tjänsten aktiveras automatiskt och stöds i produktion för alla Azure DevOps Services. Power BI-integrering och åtkomst till OData-flödet i Analytics Service är allmänt tillgängliga. Vi rekommenderar att du använder den och ger oss feedback. Tillgängliga data är versionsberoende. Den senaste versionen som stöds är v2.0, och den senaste förhandsversionen är v4.0-preview. Mer information finns i OData API-versionshantering.

Kommentar

Analytics-tjänsten installeras automatiskt och stöds i produktion för alla nya projektsamlingar för Azure DevOps Server 2020 och senare versioner. Power BI-integrering och åtkomst till OData-flödet i Analytics Service är allmänt tillgängliga. Vi rekommenderar att du använder den och ger oss feedback. Om du har uppgraderat från Azure DevOps Server 2019 kan du installera Analytics-tjänsten under uppgraderingen.

Tillgängliga data är versionsberoende. Den senaste versionen som stöds är v2.0, och den senaste förhandsversionen är v4.0-preview. Mer information finns i OData API-versionshantering.

Kommentar

Analytics-tjänsten är en förhandsversion för Azure DevOps Server 2019. Du kan aktivera eller installera den för en projektsamling. Power BI-integrering och åtkomst till OData-flödet för Analystjänsten finns i förhandsversion. Vi rekommenderar att du använder den och ger oss feedback.

Tillgängliga data är versionsberoende. Den senaste versionen som stöds är v2.0, och den senaste förhandsversionen är v4.0-preview. Mer information finns i OData API-versionshantering.

Dessa riktlinjer är våra rekommendationer som är prefixet med termerna DO, CONSIDER,AVOID och DON'T. Restriktiva regler som tillämpas av Analytics innehåller prefixet [BLOCKED]. Du bör förstå kompromisserna mellan olika lösningar. Under vissa omständigheter kan du ha datakrav som tvingar dig att bryta mot en eller flera riktlinjer. Sådana fall bör vara sällsynta. Vi rekommenderar att du har en tydlig och övertygande anledning till sådana beslut.

Dricks

Exemplen som visas i det här dokumentet baseras på en URL för Azure DevOps Services. Använd ersättningar för lokala versioner.

https://{servername}:{port}/tfs/{OrganizationName}/{ProjectName}/_odata/{version}/

Fel- och varningsmeddelanden

✔️ GRANSKA OData-svarsvarningar

Varje fråga som du kör kontrolleras mot en uppsättning fördefinierade regler. Överträdelser returnerar OData-svaret efter @vsts.warnings. Granska dessa varningar eftersom de innehåller aktuell och kontextkänslig information om hur du kan förbättra din fråga.

{
  "@odata.context": "https://{OrganizationName}.tfsallin.net/_odata/v1.0/$metadata#WorkItems",
  "@vsts.warnings": [
    "The specified query does not include a $select or $apply clause which is recommended for all queries."
  ],
  ...
}

✔️ GRANSKA OData-felmeddelanden

Frågor som bryter mot en OData-felregel resulterar i ett misslyckat svar med statuskoden 400 (felaktig begäran). Associerade meddelanden visas inte i egenskapen @vsts.warnings . I stället genererar de ett felmeddelande i message egenskapen i JSON-svaret.

{
  "error": {
  "code": "0",
  "message": "The query specified in the URI is not valid. The Snapshot tables in Analytics are intended to be used only in an aggregation."
  }
}

Begränsningar

Göra

Överväga

Spärrad

Undvik

✔️ Begränsa frågan till de projekt som du har åtkomst till

Om din fråga riktar sig mot data från ett projekt som du inte har åtkomst till returnerar frågan meddelandet "Project access denied". Kontrollera att du har åtkomst genom att se till att behörigheten Visa analys är inställd på Tillåt för alla projekt som du frågar efter. Mer information finns i Behörigheter som krävs för att få åtkomst till Analys.

Om du inte har åtkomst till ett projekt visas följande meddelande:

Frågeresultaten innehåller data i ett eller flera projekt som du inte har åtkomst till. Lägg till ett eller flera projektfilter för att ange vilka projekt som du har åtkomst till i entiteten WorkItems. Om du använder $expand eller navigeringsegenskaper krävs projektfilter för dessa entiteter.

Om du vill undvika det här problemet kan du antingen uttryckligen lägga till ett projektfilter eller använda den projektomfattningsslutpunkt som beskrivs senare i den här artikeln.

Följande fråga hämtar till exempel arbetsobjekt som tillhör projekt med namnet {projectSK1} och {projectSK2}.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=ProjectSK eq {projectSK1} or ProjectSK eq {projectSK2}
  &$select=WorkItemId, Title

✔️ ANGE projektfilter i $expand satsen om din expansion kan innehålla data i andra, potentiellt otillgängliga projekt

När du expanderar navigeringsegenskaper finns det en chans att du refererar till data från andra, otillgängliga projekt. Om du refererar till otillgängliga data får du samma felmeddelande som angavs tidigare, "Frågeresultaten innehåller data i ett eller flera projekt...". På samma sätt kan du lösa det här problemet genom att lägga till explicita projektfilter för att styra expanderade data.

Du kan göra det i den vanliga $filter satsen för enkla navigeringsegenskaper. Följande fråga frågar till exempel uttryckligen om WorkItemLinks var både länken och dess mål finns i samma projekt.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemLinks?
  $filter=ProjectSK eq {projectSK} and TargetWorkItem/ProjectSK eq {projectSK}
  &$select=LinkTypeReferenceName, SourceWorkItemId, TargetWorkItemId
  &$expand=TargetWorkItem($select=WorkItemId, Title)

I stället kan du flytta filtret för att $filter expandera alternativet i $expand -satsen. Den ändrar dock frågans semantik. Följande fråga hämtar till exempel alla länkar från ett visst projekt och expanderar villkorligt endast målet om det finns i samma projekt. Även om den är giltig kan den här metoden orsaka förvirring eftersom det kan vara svårt att avgöra om en egenskap inte expanderas eftersom den är null eller för att den har filtrerats bort. Använd endast den här lösningen om du verkligen behöver det här beteendet.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemLinks?
  $filter=ProjectSK eq {projectSK}
  &$select=LinkTypeReferenceName, SourceWorkItemId, TargetWorkItemId
  &$expand=TargetWorkItem($filter=ProjectSK eq {projectSK}; $select=WorkItemId, Title)

Alternativet $filter expandera är användbart när du använder egenskapen expandera samling, till exempel Children i WorkItems entitetsuppsättningen. Följande fråga returnerar till exempel alla arbetsobjekt från ett visst projekt tillsammans med alla deras underordnade objekt som hör hemma i samma projekt.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=ProjectSK eq {projectSK}
  &$select=WorkItemId, Title
  &$expand=Children($filter=ProjectSK eq {projectSK}; $select=WorkItemId, Title)

Ange filtret om du expanderar någon av följande egenskaper:

  • WorkItems entitetsuppsättning: Parent, Children
  • WorkItemLinks entitetsuppsättning: TargetWorkItem.

✔️ ÖVERVÄG att köra frågor med hjälp av den projektomfattande slutpunkten

Om du är intresserad av data från ett enda projekt rekommenderar vi att du använder den projektomfattande OData-slutpunkten (/{ProjectName}/_odata/v1.0). Det undviker de problem som beskrivs i de föregående två avsnitten och filtrerar implicit data till ett projekt, den refererade entitetsuppsättningen och alla expanderade navigeringsegenskaper.

Med den här förenklingen kan frågorna från föregående avsnitt skrivas om till följande formulär. Filtret i expanderingssatsen försvann inte bara, utan det finns inte heller något behov av filtret på huvudentitetsuppsättningen.

https://analytics.dev.azure.com/{OrganizationName}/{ProjectName}/_odata/{version}//WorkItemLinks?
  &$select=LinkTypeReferenceName, SourceWorkItemId, TargetWorkItemId
  &$expand=TargetWorkItem($select=WorkItemId, Title)

Frågan för underordnade arbetsobjekt är också mycket kortare och enklare.

https://analytics.dev.azure.com/{OrganizationName}/{ProjectName}/_odata/{version}//WorkItems?
  &$select=WorkItemId, Title
  &$expand=Children($select=WorkItemId, Title)

Du kan bara använda den här lösningen när fokus är data från ett enda projekt. För rapportering mellan projekt måste du använda filtreringsstrategier som beskrivs i föregående avsnitt.

✔️ Vänta eller stoppa åtgärden om frågan överskrider användningsgränserna

Om du kör många frågor, eller om frågorna kräver många resurser för att köras, kan du överskrida tjänstgränserna och tillfälligt blockeras. Om du överskrider tjänstgränserna stoppar du åtgärden eftersom risken är stor att nästa fråga som du skickar misslyckas med samma felmeddelande.

Begäran blockerades på grund av att resursen {resource} överskreds i namnområdet {namespace}.

Mer information om hastighetsbegränsning finns i Hastighetsbegränsningar. Mer information om hur du utformar effektiva OData-frågor finns i Prestandariktlinjer senare i den här artikeln.

✔️ VÄNTA eller stoppa åtgärden om frågan misslyckas med en tidsgräns

På liknande sätt som överskrider användningsgränserna bör du vänta eller stoppa åtgärden om frågan överskrider en tidsgräns. Det kan signalera ett tillfälligt problem, så du kan försöka igen en gång för att se om problemet löser sig. Beständiga timeouter indikerar dock att frågan förmodligen är för dyr för att köras. Ytterligare återförsök leder bara till att användningsgränserna överskrids och du blockeras.

TF400733: Begäran har avbrutits: Begäran har överskridit tidsgränsen för begäran. Försök igen.

Tidsgränser indikerar att en fråga kräver optimering. Mer information om hur du utformar effektiva OData-frågor finns i Prestandariktlinjer senare i den här artikeln.

❌ [BLOCKERAD] Använd inte ögonblicksbildentiteter för något annat än aggregeringar

Ögonblicksbildentitetsuppsättningar med suffixet Snapshot är speciella eftersom de modelleras som dagliga ögonblicksbilder. Du kan använda dem för att hämta ett tillstånd för entiteter som de var i slutet av varje dag tidigare. Om du till exempel har frågat och filtrerat WorkItemSnapshot till en enda WorkItemId, får du en post för varje dag sedan arbetsobjektet skapades. Att läsa in alla dessa data direkt skulle vara dyrt och skulle sannolikt överskrida användningsgränserna och blockeras. Sammansättningar på dessa entiteter är dock både tillåtna och rekommenderade. I själva verket utformades entitetsuppsättningarna för ögonblicksbilder med aggregeringsscenarier i åtanke.

Följande fråga hämtar till exempel antalet arbetsobjekt efter datum för att se hur det växte i januari 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemSnapshot?
  $apply=
    filter(DateSK ge 20200101 and DateSK le 20200131)/
    groupby((DateSK), aggregate($count as Count))

Mer information om sammansättningar finns i Sammanställa data.

✔️ Inkludera DateSK eller DateValue kolumn i groupby -sats när du aggregerar över ögonblicksbildstabeller

Eftersom alla ögonblicksbildentiteter modelleras som dagliga ögonblicksbildtabeller bör du alltid inkludera en av dagegenskaperna (DateSK eller DateValue) i grupperingssatsen. Annars kan resultatet verka felaktigt uppblåst.

Om du till exempel bara AssignedTo grupperade WorkItemSnapshot efter egenskap och aggregerade den med antal, multipliceras alla antal arbetsobjekt som tilldelats personer med antalet dagar då varje tilldelning var aktiv. Även om du kan ha en situation där det är det resultat du vill ha, är sådana fall sällsynta.

❌ [BLOCKERAD] Använd inte entitetsnycklar i resurssökvägar för entitets adressering

OData-syntax ger ett sätt att komma åt en viss entitet genom att inkludera dess nycklar direkt i URL-segmenten. Mer information finns i OData version 4.0. Del 2: URL-konventioner – 4.3 Adresseringsentiteter. Även om OData tillåter sådana adresser blockerar Analytics det. Inkludering i en fråga resulterar i följande fel.

Frågan som anges i URI:n är inte giltig. Analytics stöder inte nyckel- eller egenskapsnavigering som WorkItems(ID) eller WorkItem(Id)/AssignedTo. Om du får det felet i PowerBI skriver du om frågan för att undvika felaktig vikning som orsakar N+1-problem.

När felmeddelandena antyder kan vissa klientverktyg missbruka direkt entitetshantering. I stället för att läsa in alla data i en enda begäran kan sådana klienter välja att fråga efter varje entitet oberoende av varandra. Den här metoden rekommenderas inte eftersom det kan leda till ett stort antal begäranden. I stället rekommenderar vi att du använder explicit entitetshantering enligt beskrivningen i följande avsnitt.

✔️ DO adresserar uttryckligen entiteter med filtersatser

Om du vill hämta data för en enskild entitet bör du använda samma metod som för en samling entiteter och uttryckligen definiera filter i $filter -satsen.

Följande fråga hämtar till exempel ett enda arbetsobjekt med dess identifierare.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=WorkItemId eq {id}
  &$select=WorkItemId, Title

Om du inte är säker på vilka egenskaper du ska inkludera i ett sådant filter kan du leta upp det i metadata. Se Skapa OData-frågor för analys, URL-komponenter för att köra frågor mot metadata. Egenskaperna finns i elementet KeyEntityTypei . Och är till exempel WorkItemIdRevision nyckelkolumner för entiteten WorkItemRevision .

<EntityType Name="WorkItemRevision">
  <Key>
    <PropertyRef Name="WorkItemId"/>
    <PropertyRef Name="Revision"/>
  </Key>
  [...]
</EntityType>

❌[BLOCKERAD] Expandera Revisions inte entiteten WorkItem

Analysdatamodellen tillåter inte vissa typer av expansioner. En av dem, vilket kan vara förvånande för vissa, är samlingsegenskapen RevisionsWorkItem entiteten. Om du försöker expandera den här egenskapen får du följande felmeddelande.

Frågan som anges i URI:n är inte giltig. Egenskapen Revisioner kan inte användas i frågealternativet $expand.

Den här begränsningen infördes för att uppmuntra alla att använda den rekommenderade lösningen, som hämtar revisioner från WorkItemRevisions enligt beskrivningen i följande avsnitt.

✔️ ANVÄND WorkItemRevisions entitetsuppsättning för att läsa in alla revisioner för ett visst arbetsobjekt

Använd WorkItemRevisions varje gång du vill hämta hela historiken för ett arbetsobjekt eller en samling arbetsobjekt.

Följande fråga returnerar till exempel alla revisioner av ett arbetsobjekt med identifieraren {id} .

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemRevisions?
  $filter=WorkItemId eq {id}
  &$select=WorkItemId, Title

Om du bryr dig om den fullständiga historiken för alla arbetsobjekt som matchar vissa villkor uttrycker du den med hjälp av ett filter på navigeringsegenskapen WorkItem . Följande fråga hämtar till exempel alla revisioner av alla aktiva arbetsobjekt.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemRevisions?
  $filter=WorkItem/State eq 'Active'
  &$select=WorkItemId, Title

❌ [BLOCKERAD] Gruppera inte på distinkta kolumner

Du använder en grupperingsåtgärd för att minska antalet poster. Att använda distinkta kolumner i groupby -satsen indikerar ett problem, och frågan misslyckas omedelbart. Om du råkar råka ut för den här situationen får du följande felmeddelande.

En eller flera av de kolumner som anges i groupby-satsen i den här frågan rekommenderas inte.

Lös problemet genom att ta bort den distinkta kolumnen från groupby -satsen.

❌ [BLOCKERAD] Använd countdistinct inte aggregering

Analys stöder countdistinct inte funktionen, även om OData gör det. Även om vi planerar att lägga till stöd i framtiden är det för närvarande inte tillgängligt. En fråga som innehåller den här funktionen returnerar följande felmeddelande.

Frågor som tillämpar ett antal distinkta med en aggregering stöds inte.

❌ UNDVIK aggregeringar som kan resultera i aritmetiskt spill

I sällsynta fall kan en aggregeringsfråga stöta på problem med aritmetiskt spill. Det kan till exempel inträffa när du summerar vissa numeriska egenskaper som inte är avsedda att summeras, till exempel StackRank i arbetsobjektentiteterna. Eftersom OData-tillägget för dataaggregeringsstandarden inte ger ett sätt att omvandla en egenskap till en annan typ är det enda sättet att lösa det här problemet att ta bort den problematiska egenskapen från aggregeringen.

✔️ ANVÄND batchslutpunkt för långa frågor

Du kan få problem med långa frågor. I synnerhet kan det uppstå problem när:

  • Du kör frågor mot ett projekt med många anpassade fält.
  • Frågan konstrueras programmatiskt.

Den aktuella gränsen för OData-frågor som skickas med HTTP GET är 3 000 tecken. Om du överskrider det får du tillbaka svaret "404 Hittades inte".

HTTP/1.1 404 Not Found
Content-Length: 0

Lös problemet genom att använda OData-batchslutpunkten enligt beskrivningen i specifikationen OData Version 4.0. Del 1: Protokoll – 11.7 Batch-begäranden. Batch-funktionen har främst utformats för att gruppera flera åtgärder i en enda HTTP nyttolast för begäranden, men du kan också använda den som en lösning för frågelängdsbegränsningen. Genom att skicka en HTTP POST begäran kan du skicka en fråga med godtycklig längd och tjänsten tolkar den korrekt.

❌ [BLOCKERAD] Använd inte batchslutpunkt för att skicka flera frågor

Vi begränsar användningen av batchslutpunkten från att hantera en batch med flera begäranden. En enskild begäran kan fortfarande bara ha en fråga. Om du försöker skicka en batch med flera frågor misslyckas åtgärden med följande felmeddelande. Den enda lösningen är att dela upp frågor i flera begäranden.

Analys stöder inte bearbetning av flera åtgärder som det aktuella batchmeddelandet innehåller. Analytics använder OData-batchen för att stödja POST-begäranden, men kräver att du begränsar åtgärden till en enda begäran.

❌ [BLOCKERAD] Använd inte frågor som resulterar i fler än 800 kolumner

Vi begränsar frågor som resulterar i fler än 800 kolumner. Om du inte är tillräckligt selektiv i vilka kolumner din fråga returnerar kan du få följande felmeddelande.

VS403670: Den angivna frågan returnerar N-kolumner som är högre än den tillåtna gränsen på 800 kolumner. Använd explicita $select (inklusive i $expand) för att begränsa antalet kolumner.

Lägg till en $select-sats i frågan och för att $expand åtgärder i frågan för att undvika att överskrida den här gränsen.

❌ UNDVIK att skapa långa frågor

Vi rekommenderar att du utvärderar din metod när du skapar en lång fråga. Även om det finns många scenarier som behöver en lång fråga (till exempel komplexa filter eller en lång lista med egenskaper), ger de vanligtvis en tidig indikator på en underoptimal design.

När frågan innehåller många entitetsnycklar i frågan (till exempel WorkItemId eq {id 1} or WorkItemId eq {id 2} or ...), kan du förmodligen skriva om den. I stället för att skicka identifierarna kan du försöka definiera några andra kriterier som väljer samma uppsättning entiteter. Ibland kan du behöva ändra processen (till exempel lägga till ett nytt fält eller en tagg), men det är vanligtvis värt det. Frågor som använder mer abstrakta filter är enklare att underhålla och har större potential att fungera bättre.

Ett annat scenario som tenderar att generera långa frågor inträffar när du inkluderar många enskilda datum (till exempel DateSK eq {dateSK 1} or DateSK eq {dateSK 2} or ...). Leta efter ett annat mönster som du kan använda för att skapa ett mer abstrakt filter. Följande fråga returnerar till exempel alla arbetsobjekt som skapades på måndagen.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedOn/DayOfWeek eq 2
  &$select=WorkItemId, Title, State

✔️ ANGE tidszon när du filtrerar efter datumkolumner

Tidszonen (Edm.DateTimeOffset) exponerar all datum- och tidsinformation med en förskjutning som matchar organisationens tidszonsinställningar. Dessa data är exakta och enkla att tolka samtidigt. En annan icke-känslig konsekvens är att alla filter också måste skicka tidszonsinformationen. Om du hoppar över det får du följande felmeddelande.

Frågan som anges i URI:n är inte giltig. Ingen datetime-förskjutning har angetts. Använd något av dessa format YYYY-MM-ddZ för att ange allt sedan midnatt eller åååå-MM-ddThh:mm-hh:mm (ISO 8601 standardrepresentation av datum och tider) för att ange förskjutningen.

Lös problemet genom att lägga till tidszonsinformationen. Om du till exempel antar att organisationen är konfigurerad för att visa data i tidszonen "(UTC-08:00) Pacific Time (USA och Kanada)" hämtar följande fråga alla arbetsobjekt som skapats sedan början av 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDate ge 2020-01-01T00:00:00-08:00
  &$select=WorkItemId, Title, State

Samma lösning fungerar för tidszoner med positiva förskjutningar, men plustecknet (+) har en särskild betydelse i URI:n och du måste hantera den korrekt. Om du anger 2020-01-01T00:00:00+08:00 (med ett + tecken) som startpunkt får du följande fel.

Frågan som anges i URI:n är inte giltig. Syntaxfel vid position 31 i "CreatedDate ge 2020-01-01T0000 08:00".

Lös det genom att + ersätta tecknet med dess kodade version, %2B. Om organisationen till exempel är konfigurerad att visa data i tidszonen "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi" returnerar följande fråga alla arbetsobjekt som skapats sedan början av 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDate ge 2020-01-01T00:00:00%2B08:00
  &$select=WorkItemId, Title, State

En annan metod är att använda egenskaper för datum surrogatnyckel eftersom de inte behåller tidszonsinformationen. Följande fråga returnerar till exempel alla arbetsobjekt som skapats sedan början av 2020 oavsett organisationens inställningar.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDateSK ge 20200101
  &$select=WorkItemId, Title, State

Riktlinjer för prestanda

Göra

Gör inte det

Överväga

Undvik

✔️ MÄT effekten av att implementera en prestanda riktlinje

Precis som med eventuella prestandarekommendationer bör du inte implementera dem blint. Samla i stället alltid in baslinjen och mät effekten av de ändringar du gör. Alla riktlinjer skapades baserat på interaktioner med klienter i Analytics som hade specifika krav och utmaningar. Dessa rekommendationer ansågs vara allmänna och potentiellt användbara för alla som utformar liknande frågor. I sällsynta fall kan det dock inte ha någon effekt eller ens en negativ effekt på prestandan att följa riktlinjerna. Du måste mäta skillnaden för att märka den. Om detta skulle inträffa kan du ge feedback i communityportalen för utvecklare .

Det finns många alternativ för att mäta prestanda. Det enklaste är att köra två versioner av samma fråga direkt i webbläsaren. Observera den tid det tar i utvecklarverktygen. Du kan till exempel använda nätverkspanelen i Microsoft Edge F12 Developer Tools). Ett annat alternativ är att samla in den här informationen med hjälp av Fiddler Web Debugger Tool.

Oavsett vilken metod du använder kör du båda frågorna flera gånger. Kör till exempel frågorna 30 gånger var för att ha en tillräckligt stor exempeluppsättning. Ta sedan reda på prestandaegenskaperna. Analys följer arkitekturen för flera klientorganisationer. Andra åtgärder som utförs samtidigt kan därför påverka varaktigheten för dina frågor.

✔️ ANVÄND aggregeringstillägg

Det överlägset bästa du kan göra för att förbättra dina frågors prestanda är att använda aggregeringstillägg – OData-tillägg för dataaggregering. Med aggregeringstillägget ber du tjänsten att sammanfatta dataserversidan och returnera ett mindre svar än vad du kan hämta genom att använda samma funktion på klientsidan. Slutligen är Analytics optimerat för den här typen av frågor, så använd det.

Mer information finns i Aggregerade data.

✔️ ANGE kolumner i $select -satsen

Ange de kolumner som du bryr dig om i $select -satsen. Analys bygger på en Columnstore Index-teknik . Det innebär att data är både lagring och frågebearbetning är kolumnbaserad. Genom att minska uppsättningen egenskaper refererar du till i $select -satsen och kan minska antalet kolumner som måste genomsökas och förbättra frågans övergripande prestanda.

Följande fråga anger till exempel kolumnerna för arbetsobjekt.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $select=WorkItemId, Title, State

Kommentar

Azure DevOps stöder processanpassning. Vissa administratörer använder den här funktionen och skapar hundratals anpassade fält. Om du utelämnar $select -satsen returnerar frågan alla fält, inklusive anpassade fält.

✔️ ANGE kolumner i $select alternativet expandera i $expand -satsen

På samma sätt som riktlinjerna för $select satsen anger du egenskaperna i $select alternativet expandera i $expand -satsen. Det är lätt att glömma, men om du utelämnar det innehåller svaret alla egenskaper från det expanderade objektet.

Följande fråga anger till exempel kolumnerna för både arbetsobjektet och dess överordnade.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $select=WorkItemId, Title, State
  &$expand=Parent($select=WorkItemId, Title, State)

✔️ Definiera ett filter på RevisedDateSK när du frågar efter historiska arbetsobjektdata (WorkItemRevisions eller WorkItemSnapshot entitetsuppsättningar)

När du frågar efter historiska data är chansen stor att du är intresserad av den senaste perioden (till exempel 30 dagar, 90 dagar). På grund av hur entiteter för arbetsobjekt implementeras finns det ett bekvämt sätt för dig att skriva sådana frågor för att få bra prestanda. Varje gång du uppdaterar ett arbetsobjekt skapas en ny revision och den här åtgärden registreras i System.RevisedDate fältet, vilket gör den perfekt för historikfilter.

I Analytics visas det ändrade datumet i RevisedDate egenskaperna (Edm.DateTimeOffset) och RevisedDateSK (Edm.Int32). Använd det senare för bästa prestanda. Det är datum surrogatnyckeln och representerar det datum då en revision skapades eller har null för aktiva, ofullständiga revisioner. Om du vill ha alla datum sedan inkluderingen {startDate} lägger du till följande filter i din fråga.

RevisedDateSK eq null or RevisedDateSK gt {startDateSK}

Följande fråga returnerar till exempel antalet arbetsobjekt för varje dag sedan början av 2020. Observera att förutom det uppenbara filtret på DateSK kolumnen finns det ett andra filter på RevisedDateSK. Även om det kan verka redundant hjälper det frågemotorn att filtrera bort revisioner som inte finns i omfånget och avsevärt förbättrar frågeprestandan.

https://analytics.dev.azure.com/{OrganizationName}/_odata/v1.0/WorkItemSnapshot?
  $apply=
    filter(DateSK gt 20200101)/
    filter(RevisedDateSK eq null or RevisedDateSK gt 20200101)/
    groupby(
      (DateValue), 
      aggregate($count as Count)
    )

Kommentar

Vi kom på den här rekommendationen när vi arbetade med Burndown-widgetar. Ursprungligen definierade vi endast filter för DateSK men vi kunde inte få den här frågan att skalas bra för organisationer med stora datamängder. Under frågeprofilering märkte vi att DateSK det inte filtrerar revisioner på ett bra sätt. Först när vi har lagt till ett filter på RevisedDateSK kunde vi få bra prestanda i stor skala.
~ Produktteam

✔️ Använd ögonblicksbilder varje vecka eller månad för trendfrågor som sträcker sig över en lång tidsperiod

Som standard modelleras alla tabeller för ögonblicksbilder som dagliga faktatabeller för ögonblicksbilder. Om du frågar efter ett tidsintervall får det ett värde för varje dag. Långa tidsintervall resulterar i ett stort antal poster. Om du inte behöver så hög precision kan du använda ögonblicksbilder varje vecka eller till och med varje månad.

Du kan göra det med andra filteruttryck för att ta bort dagar som inte slutför en viss vecka eller månad. Använd egenskapen IsLastDayOfPeriod som lades till i Analytics med det här scenariot i åtanke. Den här egenskapen är av typen Microsoft.VisualStudio.Services.Analytics.Model.Period och kan avgöra om en dag slutar i olika perioder (till exempel veckor, månader och så vidare).

<EnumType Name="Period" IsFlags="true">
  <Member Name="None" Value="0"/>
  <Member Name="Day" Value="1"/>
  <Member Name="WeekEndingOnSunday" Value="2"/>
  <Member Name="WeekEndingOnMonday" Value="4"/>
  <Member Name="WeekEndingOnTuesday" Value="8"/>
  <Member Name="WeekEndingOnWednesday" Value="16"/>
  <Member Name="WeekEndingOnThursday" Value="32"/>
  <Member Name="WeekEndingOnFriday" Value="64"/>
  <Member Name="WeekEndingOnSaturday" Value="128"/>
  <Member Name="Month" Value="256"/>
  <Member Name="Quarter" Value="512"/>
  <Member Name="Year" Value="1024"/>
  <Member Name="All" Value="2047"/>
</EnumType>

Eftersom Microsoft.VisualStudio.Services.Analytics.Model.Period definieras som en uppräkning med flaggor använder du OData-operatorn has och anger fullständig typ för periodliteralerna.

IsLastDayOfPeriod has Microsoft.VisualStudio.Services.Analytics.Model.Period'Month'

Följande fråga returnerar till exempel ett antal arbetsobjekt som har definierats den sista dagen i varje månad.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItemSnapshot?
  $apply=
    filter(IsLastDayOfPeriod has Microsoft.VisualStudio.Services.Analytics.Model.Period'Month')/
    groupby(
      (DateValue), 
      aggregate($count as Count)
    )

✔️ ANVÄND Tags samlingsegenskap på arbetsobjekt när du filtrerar efter taggar

Du kan använda TagNames egenskapen med contains funktionen för att avgöra om ett arbete har markerats med en specifik tagg. Den här metoden kan dock resultera i långsamma frågor, särskilt när du söker efter flera taggar samtidigt. För bästa prestanda och resultat använder du navigeringsegenskapen Tags i stället.

Följande fråga hämtar till exempel alla arbetsobjekt som har taggats med en {tag}.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq '{tag}')
  &$select=WorkItemId, Title, State

Den här metoden fungerar också bra när du behöver filtrera på flera taggar. Följande fråga returnerar till exempel alla arbetsobjekt som har taggats med {tag1}eller{tag2}

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq {tag1} or t/TagName eq {tag2})
  &$select=WorkItemId, Title, State

Du kan också kombinera dessa filter med en "och"-operator. Följande fråga hämtar till exempel alla arbetsobjekt som har taggats med både {tag1}och{tag2}

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq {tag1}) and Tags/any(t:t/TagName eq {tag2})
  &$select=WorkItemId, Title, State

✔️ Använd TagNames egenskapen om du vill visa alla taggar i ett arbetsobjekt som text

Navigeringsegenskapen Tags, som beskrivs i föregående avsnitt, är perfekt för filtrering. Att arbeta med dem innebär dock vissa utmaningar eftersom frågan returnerar taggar i en kapslad samling. Datamodellen innehåller också en TagNames primitiv egenskap (Edm.String), som vi har lagt till för att förenkla förbrukningsscenarier för taggar. Det är ett enskilt textvärde som innehåller en lista över alla taggar i kombination med semikolonavgränsaren "; ". Använd den här egenskapen när allt du bryr dig om är att visa taggar tillsammans. Du kan kombinera den med de taggar som beskrevs tidigare.

Följande fråga hämtar till exempel alla arbetsobjekt som har taggats med en {tag}. Den returnerar arbetsobjektets ID, rubrik, tillstånd och en textrepresentation av kombinerade taggar.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq '{tag}')
  &$select=WorkItemId, Title, State, TagNames

Viktigt!

Egenskapen TagNames har en längdgräns på 1 024 tecken. Den innehåller en uppsättning taggar som passar inom den gränsen. Om ett arbetsobjekt har många taggar eller om taggarna är mycket långa TagNames ska du inte innehålla den fullständiga uppsättningen och Tag navigeringsegenskapen ska användas i stället.

❌ Använd tolower inte och toupper funktioner för att göra skiftlägesokänslig jämförelse

Om du har arbetat med andra system kan du förvänta dig att använda tolower funktionerna eller toupper för den skiftlägeskänsliga jämförelsen. Med Analytics är alla strängjämförelser skiftlägesokänsliga som standard, så du behöver inte använda några funktioner för att uttryckligen hantera det.

Följande fråga hämtar till exempel alla arbetsobjekt som är taggade med "QUALITY", "quality" eller någon annan fallkombination av det här ordet.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=Tags/any(t:t/TagName eq 'quality')
  &$select=WorkItemId, Title, State, TagNames

❌ Använd inte obundna expansioner med $levels=max

OData har möjlighet att expandera alla nivåer i en hierarkisk struktur. Till exempel har spårning av arbetsobjekt vissa entiteter där en obundna expansion kan tillämpas. Den här åtgärden fungerar bara för organisationer med en liten mängd data. Den skalas inte bra för större datamängder. Använd den inte alls om:

  • Du arbetar med stora datamängder.
  • Du utvecklar en widget och du har ingen kontroll över var widgeten installeras.

✔️ ANVÄND serverdriven växling

Om du ber om en uppsättning som är för stor för att skickas i ett enda svar tillämpar Analytics växling. Svaret innehåller endast en partiell uppsättning och en länk som gör det möjligt att hämta nästa partiella uppsättning objekt. Den här strategin beskrivs i OData-specifikationen – OData version 4.0. Del 1: Protokoll – Serverdriven växling. Genom att låta tjänsten styra växlingen får du bästa möjliga prestanda eftersom designen skiptoken har varit noggrann för att varje entitet ska vara så effektiv som möjligt.

Länken till nästa sida ingår i egenskapen @odata.nextLink .

{
  "@odata.context": "https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/$metadata#WorkItems(*)",
  "value": [
    ...
  ],
  "@odata.nextLink":"https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?$skiptoken=12345"}

Kommentar

De flesta befintliga OData-klienter kan hantera serverdriven växling automatiskt. Den här strategin används till exempel redan av följande verktyg: Power BI, SQL Server Integration Services och Azure Data Factory.

❌ Använd $top inte och $skip fråga alternativ för att implementera klientdriven växling

Med andra REST-API:er kan du ha implementerat klientdriven växling med $top och $skip frågealternativ. Använd dem inte med Analytics. Det finns flera problem med den här metoden och prestanda är ett av dem. Anta i stället den serverdrivna växlingsstrategin som beskrivs i föregående avsnitt.

✔️ ANVÄND $top frågealternativet för att begränsa antalet poster

Frågealternativet $top rekommenderas endast när det används tillsammans med $skip. Om du i ditt rapporteringsscenario bara behöver en delmängd poster (till exempel exempel exempel) är det bra att använda $top frågealternativet. Om du behöver rangordna poster enligt vissa kriterier bör du dessutom alltid använda $top i kombination med $orderby för att få ett stabilt resultat med de högst rankade posterna.

✔️ ÖVERVÄG att skriva en fråga för att returnera ett litet antal poster

Att skriva en fråga för att returnera ett litet antal poster är den mest intuitiva riktlinjen. Sträva alltid efter att bara hämta de data som du verkligen bryr dig om. Du kan uppnå det genom att göra de flesta av de kraftfulla filtreringsfunktionerna tillgängliga på OData-frågespråket.

✔️ ÖVERVÄG att begränsa antalet valda egenskaper till ett minimum

Vissa projektadministratörer anpassar sina processer kraftigt genom att lägga till anpassade fält. Omfattande anpassning kan leda till prestandaproblem när du hämtar alla tillgängliga kolumner på breda entiteter (till exempel WorkItems). Analys bygger på en Columnstore Index-teknik . Det innebär att data är både lagring och frågebearbetning är kolumnbaserad. Ju fler egenskaper en fråga refererar till, desto dyrare är det att bearbeta. Sträva alltid efter att begränsa uppsättningen egenskaper i dina frågor till det du verkligen bryr dig om i ditt rapporteringsscenario.

✔️ ÖVERVÄG att filtrera efter egenskaper för datum surrogatnyckel (DateSK suffix)

Det finns många sätt att definiera ett datumfilter. Du kan filtrera på datumegenskapen direkt (till exempel CreatedDate), dess navigeringsmotsvarighet (till exempel CreatedOnDate), eller dess surrogatnyckelrepresentation (till exempel CreatedDate). Det sista alternativet ger bästa prestanda och rekommenderas när rapporteringskraven tillåter det.

Följande fråga hämtar till exempel alla arbetsobjekt som skapats sedan början av 2020.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDateSK ge 20200101

✔️ ÖVERVÄG att filtrera på surrogatnyckelkolumner

Om du vill filtrera data på värdet för ett relaterat objekt (till exempel genom att filtrera ett arbetsobjekt efter projektnamnet) har du alltid två alternativ. Du kan antingen använda navigeringsegenskapen (till exempel Project/ProjectName) eller samla in surrogatnyckeln i förväg och använda den direkt i frågan (till exempel ProjectSK).

Om du skapar en widget rekommenderar vi att du använder det senare alternativet. När nyckeln skickas som en del av frågan minskas antalet entitetsuppsättningar som måste röras och prestandan förbättras.

Följande fråga filtrerar WorkItems till exempel med egenskapen ProjectSK i stället Project/ProjectName för navigeringsegenskapen.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=ProjectSK eq {projectSK}

❌UNDVIK att använda Parent, Childreneller Revisions egenskaper i satserna $filter eller $expand

Arbetsobjekt är de dyraste entiteterna i hela datamodellen. De har flera navigeringsegenskaper som du kan använda för att komma åt relaterade arbetsobjekt: Parent, Children, Revisions. Varje gång du använder dem i en fråga förväntar du dig dock att prestandan försämras. Fråga alltid om du verkligen behöver någon av dessa egenskaper och eventuellt uppdatera din design.

I stället för att Parentexpandera kan du till exempel hämta fler arbetsobjekt och använda ParentWorkItemId egenskapen för att rekonstruera den fullständiga hierarkiklientsidan. Utföra sådan optimering från fall till fall.

✔️ ÖVERVÄG att skicka VSTS.Analytics.MaxSize inställningar i rubriken

När du kör en fråga vet du inte hur många poster som frågan returnerar. Skicka antingen en annan fråga med aggregeringar eller följ alla nästa länkar och hämta hela datamängden. Analytics respekterar VSTS.Analytics.MaxSize inställningar, vilket gör att du kan misslyckas snabbt i de instanser som datamängden är större än vad klienten kan acceptera.

Det här alternativet är användbart i dataexportscenarier. Om du vill använda den måste du lägga Prefer till huvudet i HTTP-begäran och ange VSTS.Analytics.MaxSize ett icke-negativt värde. Värdet VSTS.Analytics.MaxSize representerar det maximala antalet poster som du kan acceptera. Om du anger noll används ett standardvärde på 200 K.

Följande fråga returnerar till exempel arbetsobjekt om datamängden är mindre eller lika med 1 000 poster.

GET https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems HTTP/1.1
User-Agent: {application}
Prefer: VSTS.Analytics.MaxSize=1000
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Host: analytics.dev.azure.com/{OrganizationName}

Om datamängden överskrider gränsen på 1 000 poster misslyckas frågan omedelbart med följande fel.

Frågeresultatet innehåller 1 296 rader och överskrider den maximala tillåtna storleken 1 000. Minska antalet poster genom att använda ytterligare filter

Information om hur du anger maximal sidstorlek finns i egenskapen ODataPreferenceHeader.MaxPageSize.

Riktlinjer för frågeformat

✔️ Använd $count virtuell egenskap i aggregeringsmetoderna

Vissa entiteter exponerar Count egenskapen. De gör vissa rapporteringsscenarier enklare när data exporteras till en annan lagringsplats. Du bör dock inte använda dessa kolumner i sammansättningar i OData-frågor. Använd den $count virtuella egenskapen i stället.

Följande fråga returnerar till exempel det totala antalet arbetsobjekt.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $apply=aggregate($count as Count)

❌ UNDVIK att använda $count virtuell egenskap i URL-segmentet

Även om OData Standard låter dig använda $count virtuell egenskap för entitetsuppsättningar (till exempel _odata/v1.0/WorkItems/$count), kan inte alla klienter tolka svaret korrekt. Därför rekommenderar vi att du använder aggregeringar i stället.

Följande fråga returnerar till exempel det totala antalet arbetsobjekt.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $apply=aggregate($count as Count)

✔️ ÖVERVÄG att använda parameteralias för att separera flyktiga delar av frågan

Parameteralias ger en elegant lösning för att extrahera flyktiga delar som parametervärden från huvudfrågetexten. Du kan använda dem i uttryck som utvärderar:

  • Ett primitivt värde
  • Ett komplext värde
  • En samling primitiva eller komplexa värden.

Mer information finns i OData version 4.0. Del 2: URL-konventioner – 5.1.1.13 Parameteralias. Parametrar är användbara när frågetexten används som en mall som kan instansieras med användaringivna värden.

Följande fråga använder @createdDateSK till exempel parametern för att separera värdet från filteruttrycket.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=CreatedDateSK ge @createdDateSK
  &$select=WorkItemId, Title, State
  &@createdDateSK=20200101

❌ UNDVIK blandning $apply och $filter satser i en enda fråga

Om du vill lägga filter till i din fråga har du två alternativ. Du kan antingen göra det med $filter satsen eller $apply=filter() kombinationen. Vart och ett av dessa alternativ fungerar bra på egen hand, men om du kombinerar dem kan det leda till oväntade resultat.

Trots den förväntan man kan ha definierar OData tydligt en utvärderingsordning. Dessutom $apply har -satsen prioritet framför $filter. Därför bör du välja ett eller annat men undvika de här två filteralternativen i en enda fråga. Det är viktigt om frågorna genereras automatiskt.

Följande fråga filtrerar till exempel först arbetsobjekt efter StoryPoint gt 5, aggregerar resultat efter är sökvägen och filtrerar slutligen resultatet efter StoryPoints gt 2. Med den här utvärderingsordningen returnerar frågan alltid en tom uppsättning.

https://analytics.dev.azure.com/{OrganizationName}/_odata/{version}/WorkItems?
  $filter=StoryPoints gt 2
  $apply=
    filter(StoryPoints gt 5)/
    groupby(
      (Area/AreaPath),
      aggregate(StoryPoints with sum as StoryPoints)
    )

✔️ ÖVERVÄG att strukturera frågan så att den matchar OData-utvärderingsordningen

Eftersom blandning $apply och filter satser i en enda fråga kan leda till potentiell förvirring rekommenderar vi att du strukturerar dina frågesatser så att de matchar utvärderingsordningen.

  1. $apply
  2. $filter
  3. $orderby
  4. $expand
  5. $select
  6. $skip
  7. $top

✔️ ÖVERVÄG att granska OData-funktioner som beskrivs i metadataanteckningarna

När du är osäker på vilka OData-funktioner analytics stöder kan du söka efter anteckningar i metadata. OData Technical Committee (OASIS Open Data Protocol) på en TC GitHub-lagringsplats har en lista över tillgängliga anteckningar.

Till exempel är listan över filterfunktioner som stöds tillgänglig i Org.OData.Capabilities.V1.FilterFunctions anteckningar i entitetscontainern.

<Annotation Term="Org.OData.Capabilities.V1.FilterFunctions">
  <Collection>
  <String>contains</String>
  <String>endswith</String>
  [...]
  </Collection>
</Annotation>

En annan användbar kommentar är Org.OData.Capabilities.V1.ExpandRestrictions, som förklarar vilka navigeringsegenskaper du inte kan använda i $expand -satsen. Följande kommentar förklarar till exempel att det inte går att Revisions expandera entitetsuppsättningen WorkItems .

<EntitySet Name="WorkItems" EntityType="Microsoft.VisualStudio.Services.Analytics.Model.WorkItem">
  [...]
  <Annotation Term="Org.OData.Capabilities.V1.ExpandRestrictions">
    <Record>
      <PropertyValue Property="Expandable" Bool="true"/>
      <PropertyValue Property="NonExpandableProperties">
        <Collection>
          <NavigationPropertyPath>Revisions</NavigationPropertyPath>
        </Collection>
      </PropertyValue>
    </Record>
  </Annotation>
</EntitySet>