Directrices de consulta de OData Analytics para Azure DevOps

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

Los desarrolladores de extensiones pueden beneficiarse siguiendo las instrucciones proporcionadas en este artículo para diseñar consultas de OData eficaces en Analytics para Azure DevOps. Seguir estas instrucciones ayuda a garantizar que las consultas tengan un buen rendimiento para el tiempo de ejecución y el consumo de recursos. Las consultas que no cumplen estas directrices pueden dar lugar a un rendimiento deficiente, con tiempos de espera de informes largos, consultas que superan el consumo de recursos permitido o bloqueos de servicio.

Nota:

El servicio Analytics se habilita automáticamente y se admite en producción para todos los servicios de Azure DevOps. La integración de Power BI y el acceso a la fuente OData del servicio Analytics están disponibles con carácter general. Le recomendamos que lo use y nos envíe sus comentarios. Los datos disponibles dependen de la versión. La versión más reciente admitida es v2.0y la versión preliminar más reciente es v4.0-preview. Para obtener más información, consulte Control de versiones de la API de OData.

Nota:

El servicio Analytics se instala y admite automáticamente en producción para todas las colecciones de proyectos nuevas para Azure DevOps Server 2020 y versiones posteriores. La integración de Power BI y el acceso a la fuente OData del servicio Analytics están disponibles con carácter general. Le recomendamos que lo use y nos envíe sus comentarios. Si ha actualizado desde Azure DevOps Server 2019, puede instalar el servicio Analytics durante la actualización.

Los datos disponibles dependen de la versión. La versión más reciente admitida es v2.0y la versión preliminar más reciente es v4.0-preview. Para obtener más información, consulte Control de versiones de la API de OData.

Nota:

El servicio Analytics está en versión preliminar para Azure DevOps Server 2019. Puede habilitarlo o instalarlo para una colección de proyectos. La integración y el acceso de Power BI a la fuente OData del servicio Analytics se encuentran en versión preliminar. Le recomendamos que lo use y nos envíe sus comentarios.

Los datos disponibles dependen de la versión. La versión más reciente admitida es v2.0y la versión preliminar más reciente es v4.0-preview. Para obtener más información, consulte Control de versiones de la API de OData.

Estas directrices son nuestras recomendaciones prefijos con los términos DO, CONSIDER, AVOID y DON'T. Las reglas restrictivas aplicadas por Analytics contienen el prefijo [BLOCKED]. Debe comprender las ventajas entre diferentes soluciones. En determinadas circunstancias, es posible que tenga requisitos de datos que le obliguen a infringir una o varias directrices. Estos casos deben ser poco frecuentes. Le recomendamos que tenga una razón clara y convincente para estas decisiones.

Sugerencia

Los ejemplos que se muestran en este documento se basan en una dirección URL de Azure DevOps Services. Use sustituciones para versiones locales.

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

Mensajes de error y advertencia

✔️ Revise las advertencias de respuesta de OData.

Cada consulta que ejecute se comprueba con un conjunto de reglas predefinidas. Las infracciones devuelven la respuesta de OData después de @vsts.warnings. Revise estas advertencias a medida que proporcionan información actual y contextual sobre cómo mejorar la consulta.

{
  "@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."
  ],
  ...
}

✔️ Revise los mensajes de error de OData.

Las consultas que infringen una regla de error de OData producen una respuesta con error con un código de estado 400 (solicitud incorrecta). Los mensajes asociados no aparecen dentro de la @vsts.warnings propiedad . En su lugar, generan un mensaje de error en la propiedad en la message respuesta JSON.

{
  "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."
  }
}

Restricciones

Qué hacer

Tenga en cuenta que:

Bloqueado

Evite

✔️ Limite la consulta a los proyectos a los que tiene acceso

Si la consulta tiene como destino los datos de un proyecto al que no tiene acceso, la consulta devuelve un mensaje "Acceso denegado del proyecto". Para asegurarse de que tiene acceso, asegúrese de que el permiso Ver análisis esté establecido en Permitir para todos los proyectos que consulte. Para más información, consulte Permisos necesarios para acceder a Analytics.

Si no tiene acceso a un proyecto, se muestra el siguiente mensaje:

Los resultados de la consulta incluyen datos en uno o varios proyectos para los que no tiene acceso. Agregue uno o varios filtros de proyectos para especificar los proyectos a los que tiene acceso en la entidad "WorkItems". Si usa $expand o propiedades de navegación, se requiere el filtro de proyecto para esas entidades.

Para solucionar este problema, puede agregar explícitamente un filtro de proyecto o usar el punto de conexión con ámbito de proyecto, como se explica más adelante en este artículo.

Por ejemplo, la consulta siguiente captura los elementos de trabajo que pertenecen a proyectos denominados {projectSK1} y {projectSK2}.

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

✔️ ESPECIFIQUE el filtro de proyecto dentro de la cláusula si la $expand expansión podría incluir datos en otros proyectos potencialmente inaccesibles.

Al expandir las propiedades de navegación, es posible que termine haciendo referencia a datos de otros proyectos inaccesibles. Si hace referencia a datos inaccesibles, recibirá el mismo mensaje de error enumerado anteriormente, "Los resultados de la consulta incluyen datos en uno o varios proyectos...". De forma similar, puede resolver este problema agregando filtros de proyecto explícitos para controlar los datos expandidos.

Puede hacerlo en la cláusula regular $filter para propiedades de navegación sencillas. Por ejemplo, la siguiente consulta solicita explícitamente dónde WorkItemLinks existe tanto el vínculo como su destino en el mismo proyecto.

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)

En su lugar, puede mover el filtro para $filter expandir la opción en la $expand cláusula . Sin embargo, cambia la semántica de la consulta. Por ejemplo, la consulta siguiente obtiene todos los vínculos de un proyecto determinado y expande condicionalmente el destino solo si existe en el mismo proyecto. Aunque es válido, este enfoque puede causar confusión, ya que puede ser difícil determinar si una propiedad no está expandida porque es null o porque se ha filtrado. Use esta solución solo si realmente necesita este comportamiento concreto.

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)

La $filter opción de expansión es útil cuando se usa la propiedad de la colección expand, como Children en el WorkItems conjunto de entidades. Por ejemplo, la consulta siguiente devuelve todos los elementos de trabajo de un proyecto determinado junto con todos sus elementos secundarios que pertenecen al mismo proyecto.

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)

Especifique el filtro si expande una de las siguientes propiedades:

  • WorkItems conjunto de entidades: Parent, Children
  • WorkItemLinks conjunto de entidades: TargetWorkItem.

✔️ CONSIDERE la posibilidad de consultar mediante el punto de conexión con ámbito de proyecto

Si está interesado en los datos de un solo proyecto, se recomienda usar el punto de conexión de OData con ámbito de proyecto (/{ProjectName}/_odata/v1.0). Evita los problemas descritos en las dos secciones anteriores y filtra implícitamente los datos en un proyecto, el conjunto de entidades al que se hace referencia y todas las propiedades de navegación expandidas.

Con esta simplificación, las consultas de la sección anterior se podrían volver a escribir en el siguiente formulario. No solo desapareció el filtro de la cláusula expand, sino que tampoco es necesario el filtro en el conjunto de entidades principal.

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

La consulta para elementos secundarios del elemento de trabajo también es mucho más corta y sencilla.

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

Puede aplicar esta solución solo cuando el enfoque sea datos de un solo proyecto. Para los informes entre proyectos, debe usar estrategias de filtrado descritas en las secciones anteriores.

✔️ Espere o detenga la operación si la consulta supera los límites de uso.

Si ejecuta muchas consultas o las consultas requieren que se ejecuten muchos recursos, es posible que supere los límites de servicio y se bloquee temporalmente. Si supera los límites de servicio, detenga la operación como probabilidades de que se produzca un error en la siguiente consulta que envíe con el mismo mensaje de error.

Se bloqueó la solicitud debido a la superación del uso del recurso '{resource}' en el espacio de nombres '{namespace}'.

Para obtener más información sobre la limitación de velocidad, consulte Límites de velocidad. Para obtener información sobre cómo diseñar consultas OData eficaces, consulte Directrices de rendimiento más adelante en este artículo.

✔️ Espere o detenga la operación si se produce un error en la consulta con un tiempo de espera

De forma similar a superar los límites de uso, debe esperar o detener la operación si la consulta se encuentra en un tiempo de espera. Podría indicar un problema transitorio, por lo que puede volver a intentarlo una vez para ver si el problema se resuelve. Sin embargo, los tiempos de espera persistentes indican que la consulta probablemente es demasiado costosa para ejecutarse. Los reintentos adicionales solo dan lugar a superar los límites de uso y se bloquean.

TF400733: la solicitud se ha cancelado: la solicitud ha superado el tiempo de espera de la solicitud, inténtelo de nuevo.

Los tiempos de espera indican que una consulta requiere optimización. Para obtener información sobre cómo diseñar consultas de OData eficaces, consulte Directrices de rendimiento más adelante en este artículo.

❌ [BLOQUEADO] NO use entidades de instantáneas para nada distinto de las agregaciones.

Los conjuntos de entidades de instantáneas con el Snapshot sufijo son especiales porque se modelan como instantáneas diarias. Puede usarlos para obtener un estado de entidades tal como estaban al final de cada día en el pasado. Por ejemplo, si consulta WorkItemSnapshot y filtra a un solo WorkItemId, obtendrá un registro por cada día desde que se creó el elemento de trabajo. Cargar directamente todos estos datos sería costoso y probablemente superaría los límites de uso y se bloquearía. Sin embargo, se permiten y recomiendan agregaciones en estas entidades. De hecho, los conjuntos de entidades de instantáneas se diseñaron teniendo en cuenta escenarios de agregación.

Por ejemplo, la consulta siguiente obtiene el número de elementos de trabajo según la fecha para observar cómo creció en enero de 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))

Para más información sobre las agregaciones, consulte Datos agregados.

✔️ DateSK Incluir o DateValue columna en groupby la cláusula al agregar sobre tablas de instantáneas

Dado que todas las entidades de instantánea se modelan como tablas de instantáneas diarias, siempre debe incluir una de las propiedades del día (DateSK o DateValue) en la cláusula de agrupación. De lo contrario, el resultado puede aparecer incorrectamente inflado.

Por ejemplo, si agrupa WorkItemSnapshot solo por AssignedTo propiedad y lo agrega con recuento, todos los números de elementos de trabajo asignados a las personas se multiplicarían por el número de días en que cada asignación estaba activa. Aunque puede tener una situación en la que sea el resultado que desee, estos casos son poco frecuentes.

❌ [BLOQUEADO] NO use claves de entidad en las rutas de acceso de recursos para el direccionamiento de entidades

La sintaxis de OData proporciona una manera de acceder a una entidad determinada mediante la inclusión de sus claves directamente en los segmentos de dirección URL. Para obtener más información, vea OData Versión 4.0. Parte 2: Convenciones de dirección URL: 4.3 Entidades de direccionamiento. Aunque OData permite este direccionamiento, Analytics lo bloquea. La inclusión dentro de una consulta produce el siguiente error.

La consulta especificada en el URI no es válida. Analytics no admite la navegación de claves o propiedades, como WorkItems(Id) o WorkItem(Id)/AssignedTo. Si recibe ese error en PowerBI, vuelva a escribir la consulta para evitar un plegado incorrecto que cause un problema de N+1.

A medida que se sugieren los mensajes de error, ciertas herramientas de cliente pueden abusar del direccionamiento directo de entidades. En lugar de cargar todos los datos en una sola solicitud, estos clientes pueden optar por consultar cada entidad de forma independiente. Esta práctica no se recomienda, ya que puede dar lugar a un gran número de solicitudes. En su lugar, se recomienda usar el direccionamiento explícito de entidades como se explica en la sección siguiente.

✔️ Direccione explícitamente entidades con cláusulas de filtro

Si desea capturar datos para una sola entidad, debe usar el mismo enfoque que para una colección de entidades y definir explícitamente filtros en la $filter cláusula .

Por ejemplo, la consulta siguiente obtiene un único elemento de trabajo por su identificador.

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

Si no está seguro de qué propiedades debe incluir en este filtro, puede buscarlas en los metadatos. Consulte Construcción de consultas de OData para Analytics, componentes de dirección URL para consultar los metadatos. Las propiedades están en el Key elemento de EntityType. Por ejemplo, WorkItemId y Revision son columnas de clave para la WorkItemRevision entidad.

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

❌ [BLOQUEADO] NO expandir Revisions la WorkItem entidad

El modelo de datos de Analytics no permite determinados tipos de expansiones. Uno de ellos, que puede ser sorprendente para algunos, es la Revisions propiedad de colección de la WorkItem entidad. Si intenta expandir esta propiedad, recibirá el siguiente mensaje de error.

La consulta especificada en el URI no es válida. La propiedad "Revisions" no se puede usar en la opción de consulta $expand.

Esta restricción se ha puesto en marcha para animar a todos a usar la solución recomendada, que está capturando revisiones WorkItemRevisions como se explica en la sección siguiente.

✔️ WorkItemRevisions Use el conjunto de entidades para cargar todas las revisiones de un elemento de trabajo determinado.

Use WorkItemRevisions cada vez que desee capturar el historial completo de un elemento de trabajo o una colección de elementos de trabajo.

Por ejemplo, la consulta siguiente devuelve todas las revisiones de un elemento de trabajo con el {id} identificador .

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

Si le interesa el historial completo de todos los elementos de trabajo que coinciden con determinados criterios, expréselo mediante un filtro en la propiedad de WorkItem navegación. Por ejemplo, la consulta siguiente obtiene todas las revisiones de todos los elementos de trabajo activos actualmente.

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

❌ [BLOQUEADO] NO agrupar en columnas distintas

Use una operación de agrupación para reducir el número de registros. El uso de columnas distintas en la groupby cláusula indica un problema y la consulta produce un error inmediatamente. Si se produce accidentalmente esta situación, recibirá el siguiente mensaje de error.

No se recomienda una o varias de las columnas especificadas en la cláusula groupby de esta consulta.

Para resolver este problema, quite la columna distinta de la groupby cláusula .

❌ [BLOQUEADO] NO usar countdistinct la agregación

Analytics no admite la countdistinct función, aunque OData sí. Aunque planeamos agregar compatibilidad en el futuro, actualmente no está disponible. Una consulta que contiene esta función devuelve el siguiente mensaje de error.

No se admiten las consultas que aplican un recuento distinto con una agregación.

❌ EVITAR agregaciones que pueden dar lugar a desbordamiento aritmético

En raras ocasiones, una consulta de agregación puede encontrarse con problemas de desbordamiento aritmético. Por ejemplo, puede ocurrir cuando se suman algunas propiedades numéricas que no están pensadas para su suma, como StackRank en las entidades del elemento de trabajo. Dado que la extensión de OData para el estándar de agregación de datos no proporciona una manera de convertir una propiedad a otro tipo, la única manera de resolver este problema es quitar la propiedad problemática de la agregación.

✔️ Use el punto de conexión por lotes para consultas largas.

Puede incurrir en problemas con consultas largas. En particular, pueden producirse problemas cuando:

  • Puede consultar un proyecto con muchos campos personalizados.
  • La consulta se construye mediante programación.

El límite actual de consultas de OData enviadas con HTTP GET es de 3000 caracteres. Si lo supera, obtendrá una respuesta "404 No encontrado".

HTTP/1.1 404 Not Found
Content-Length: 0

Para resolver este problema, use el punto de conexión por lotes de OData como se explica en la especificación OData Versión 4.0. Parte 1: Protocolo: 11.7 Solicitudes por lotes. La funcionalidad batch se diseñó principalmente para agrupar varias operaciones en una sola HTTP carga de solicitud, pero también puede usarla como solución alternativa para la limitación de longitud de la consulta. Al enviar una HTTP POST solicitud, puede pasar una consulta de una longitud arbitraria y el servicio lo interpreta correctamente.

❌ [BLOQUEADO] NO use el punto de conexión por lotes para enviar varias consultas.

Se restringe el uso del punto de conexión por lotes para controlar un lote de varias solicitudes. Una sola solicitud todavía puede tener una sola consulta. Si intenta enviar un lote de varias consultas, se produce un error en la operación con el siguiente mensaje de error. La única solución es dividir las consultas en varias solicitudes.

Analytics no admite el procesamiento de varias operaciones que contiene el mensaje por lotes actual. Analytics usa el lote de OData para admitir solicitudes POST, pero requiere que limite la operación a una sola solicitud.

❌ [BLOQUEADO] NO use consultas que dan lugar a más de 800 columnas

Se restringen las consultas que dan como resultado más de 800 columnas. Si no es lo suficientemente selectivo en qué columnas devuelve la consulta, puede recibir el siguiente mensaje de error.

VS403670: la consulta especificada devuelve columnas "N", que es mayor que el límite permitido de 800 columnas. Use $select explícitas (incluidas las opciones de $expand) para limitar el número de columnas.

Agregue una cláusula $select a la consulta y, a $expand operaciones de la consulta, para evitar superar este límite.

❌ EVITAR la creación de consultas largas

Se recomienda evaluar el enfoque cada vez que cree una consulta larga. Aunque hay muchos escenarios que necesitan una consulta larga (por ejemplo, filtros complejos o una larga lista de propiedades), normalmente proporcionan un indicador temprano de un diseño poco óptimo.

Cuando la consulta contiene muchas claves de entidad en la consulta (por ejemplo, WorkItemId eq {id 1} or WorkItemId eq {id 2} or ...), es probable que pueda volver a escribirla. En lugar de pasar los identificadores, intente definir otros criterios que seleccionen el mismo conjunto de entidades. A veces, es posible que tenga que modificar el proceso (por ejemplo, agregar un nuevo campo o etiqueta), pero normalmente vale la pena. Las consultas que usan filtros más abstractos son más fáciles de mantener y tienen un mayor potencial para funcionar mejor.

Otro escenario que tiende a generar consultas largas se produce cuando se incluyen muchas fechas individuales (por ejemplo, DateSK eq {dateSK 1} or DateSK eq {dateSK 2} or ...). Busque otro patrón que puede usar para crear un filtro más abstracto. Por ejemplo, la consulta siguiente devuelve todos los elementos de trabajo que se crearon el lunes.

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

✔️ ESPECIFIQUE la zona horaria al filtrar en columnas de fecha.

La zona horaria (Edm.DateTimeOffset) expone toda la información de fecha y hora con un desplazamiento que coincide con la configuración de zona horaria de la organización. Estos datos son precisos y sencillos de interpretar al mismo tiempo. Otra consecuencia noobviosa es que todos los filtros también tienen que pasar la información de la zona horaria. Si lo omite, recibirá el siguiente mensaje de error.

La consulta especificada en el URI no es válida. No se especificó ningún desplazamiento de fecha y hora. Use cualquiera de estos formatos AAAA-MM-ddZ para especificar todo desde medianoche o aaaa-MM-ddThh:mm-hh:mm (representación estándar ISO 8601 de fechas y horas) para especificar el desplazamiento.

Para solucionar este problema, agregue la información de zona horaria. Por ejemplo, suponiendo que la organización esté configurada para mostrar datos en la zona horaria "(UTC-08:00) Hora del Pacífico (EE. UU. y Canadá)", la siguiente consulta obtiene todos los elementos de trabajo creados desde principios de 2020.

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

La misma solución funciona para zonas horarias con desplazamientos positivos; sin embargo, el carácter más (+) tiene un significado especial en el URI y debe controlarlo correctamente. Si especifica 2020-01-01T00:00:00+08:00 (con un + carácter) como punto de partida, obtendrá el siguiente error.

La consulta especificada en el URI no es válida. Error de sintaxis en la posición 31 en "CreatedDate ge 2020-01-01T0000 08:00".

Para resolverlo, reemplace el + carácter por su versión codificada, %2B. Por ejemplo, suponiendo que la organización está configurada para mostrar datos en la zona horaria "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", la siguiente consulta devuelve todos los elementos de trabajo creados desde principios de 2020.

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

Un enfoque alternativo consiste en usar las propiedades clave suplentes de fecha, ya que no mantienen la información de la zona horaria. Por ejemplo, la consulta siguiente devuelve todos los elementos de trabajo creados desde principios de 2020, independientemente de la configuración de la organización.

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

Directrices de rendimiento

Qué hacer

No seas

Tenga en cuenta que:

Evite

✔️ Medición del efecto de implementar una guía de rendimiento

Al igual que con las recomendaciones de rendimiento, no debe implementarlas ciegamente. En su lugar, capture siempre la línea base y mida el efecto de los cambios que realice. Todas las directrices se crearon en función de las interacciones con los clientes de Analytics que tenían requisitos y desafíos específicos. Estas recomendaciones se consideraron generales y potencialmente útiles para cualquier persona que diseña consultas similares. Sin embargo, en raras ocasiones, seguir las directrices podría no tener ningún efecto o incluso un efecto negativo en el rendimiento. Debe medir la diferencia para observarla. Si esto ocurre, proporcione comentarios en el portal de la comunidad de desarrolladores.

Hay muchas opciones para medir el rendimiento. La más sencilla es ejecutar dos versiones de la misma consulta directamente en el explorador. Observe el tiempo que tarda en las herramientas de desarrollo. Por ejemplo, puede usar el panel Red en Microsoft Edge F12 Developer Tools). Otra opción es capturar esta información mediante la herramienta Fiddler Web Debugger.

Sea cual sea el enfoque, ejecute ambas consultas varias veces. Por ejemplo, ejecute las consultas 30 veces cada una para tener un conjunto de muestras suficientemente grande. A continuación, descubra las características de rendimiento. El análisis sigue la arquitectura multiinquilino. Por lo tanto, otras operaciones que se producen al mismo tiempo pueden afectar a la duración de las consultas.

✔️ Uso de extensiones de agregación

Lo mejor que puede hacer para mejorar el rendimiento de las consultas es usar la extensión de agregación: extensión OData para agregación de datos. Con la extensión de agregación, pida al servicio que resuma el lado servidor de datos y devuelva una respuesta más pequeña que lo que se puede capturar aplicando el mismo lado cliente de función. Por último, Analytics está optimizado para este tipo de consultas, por lo que se usa.

Para más información, consulte Datos agregados.

✔️ Especificación de columnas en la $select cláusula

Especifique las columnas que le interesan en la $select cláusula . El análisis se basa en una tecnología de índice de almacén de columnas. Esto significa que los datos son tanto el almacenamiento como el procesamiento de consultas se basan en columnas. Al reducir el conjunto de propiedades, se hace referencia a la cláusula , $select puede reducir el número de columnas que se deben examinar y mejorar el rendimiento general de la consulta.

Por ejemplo, la consulta siguiente especifica las columnas de los elementos de trabajo.

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

Nota:

Azure DevOps admite la personalización de procesos. Algunos administradores usan esta característica y crean cientos de campos personalizados. Si omite la cláusula , la $select consulta devuelve todos los campos, incluidos los campos personalizados.

✔️ Especificar columnas en la $select opción de expansión dentro de la $expand cláusula

De forma similar a las directrices de la $select cláusula, especifique las propiedades de la $select opción expand dentro de la $expand cláusula . Es fácil olvidar, pero si lo omite, la respuesta contiene todas las propiedades del objeto expandido.

Por ejemplo, la consulta siguiente especifica las columnas para el elemento de trabajo y su elemento primario.

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

✔️ Defina un filtro al RevisedDateSK consultar datos históricos de elementos de trabajo (WorkItemRevisions o WorkItemSnapshot conjuntos de entidades)

Al consultar datos históricos, es probable que le interese el período más reciente (por ejemplo, 30 días, 90 días). Debido a cómo se implementan las entidades de elementos de trabajo, hay una manera cómoda de escribir estas consultas para obtener un rendimiento excelente. Cada vez que actualiza un elemento de trabajo, crea una nueva revisión y registra esta acción en el System.RevisedDate campo, lo que hace que sea perfecto para los filtros de historial.

En Analytics, la fecha revisada se muestra en las RevisedDate propiedades (Edm.DateTimeOffset) y RevisedDateSK (Edm.Int32). Para obtener el mejor rendimiento, use este último. Es la clave suplente de fecha y representa la fecha en que se creó una revisión o tiene null revisiones activas e incompletas. Si desea todas las fechas desde el {startDate} inclusive, agregue el siguiente filtro a la consulta.

RevisedDateSK eq null or RevisedDateSK gt {startDateSK}

Por ejemplo, la consulta siguiente devuelve el número de elementos de trabajo de cada día desde principios de 2020. Tenga en cuenta que, aparte del filtro obvio de la DateSK columna, hay un segundo filtro en RevisedDateSK. Aunque puede parecer redundante, ayuda al motor de consultas a filtrar las revisiones que no están en el ámbito y mejora significativamente el rendimiento de las consultas.

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)
    )

Nota:

Hemos llegado a esta recomendación cuando estamos trabajando en widgets de Burndown. Inicialmente, definimos filtros solo para DateSK , pero no pudimos obtener esta consulta para escalar bien para las organizaciones con grandes conjuntos de datos. Durante la generación de perfiles de consultas, hemos observado que DateSK no filtra bien las revisiones. Solo después de agregar un filtro en RevisedDateSK hemos podido obtener un gran rendimiento a escala.
~ Equipo de productos

✔️ Use instantáneas semanales o mensuales para consultas de tendencia que abarquen un período de tiempo largo

De forma predeterminada, todas las tablas de instantáneas se modelan como tablas de hechos de instantáneas diarias. Si consulta un intervalo de tiempo, obtiene un valor para cada día. Los intervalos de tiempo largos dan lugar a un gran número de registros. Si no necesita una precisión tan alta, puede usar instantáneas semanales o incluso mensuales.

Puede hacerlo con otras expresiones de filtro para quitar días que no terminen una semana o mes determinado. Use la IsLastDayOfPeriod propiedad , que se agregó a Analytics teniendo en cuenta este escenario. Esta propiedad es de tipo Microsoft.VisualStudio.Services.Analytics.Model.Period y puede determinar si un día finaliza en distintos períodos (por ejemplo, semanas, meses, etc.).

<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>

Puesto Microsoft.VisualStudio.Services.Analytics.Model.Period que se define como una enumeración con marcas, use el operador OData has y especifique el tipo completo para los literales de punto.

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

Por ejemplo, la consulta siguiente devuelve un recuento de elementos de trabajo definidos en el último día de cada mes.

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)
    )

✔️ Use la Tags propiedad de colección en los elementos de trabajo al filtrar por etiquetas

Puede usar la TagNames propiedad con la contains función para determinar si un trabajo se ha marcado con una etiqueta específica. Sin embargo, este enfoque podría dar lugar a consultas lentas, especialmente al comprobar varias etiquetas al mismo tiempo. Para obtener el mejor rendimiento y resultados, use la propiedad de Tags navegación en su lugar.

Por ejemplo, la consulta siguiente obtiene todos los elementos de trabajo etiquetados con un {tag}.

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

Este enfoque también funciona bien cuando es necesario filtrar por varias etiquetas. Por ejemplo, la consulta siguiente devuelve todos los elementos de trabajo etiquetados con {tag1}o{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

También puede combinar estos filtros con un operador "and". Por ejemplo, la consulta siguiente obtiene todos los elementos de trabajo etiquetados con y {tag1}{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

✔️ Use la TagNames propiedad si desea mostrar todas las etiquetas de un elemento de trabajo como texto.

La propiedad Tagsde navegación , descrita en la sección anterior, es excelente para el filtrado. Sin embargo, trabajar con ellos presenta algunos desafíos a medida que la consulta devuelve etiquetas en una colección anidada. El modelo de datos también contiene una TagNames propiedad primitiva (Edm.String), que agregamos para simplificar los escenarios de consumo de etiquetas. Es un valor de texto único que contiene una lista de todas las etiquetas combinadas con un separador de punto y coma "; ". Use esta propiedad cuando todo lo que le interese es mostrar etiquetas juntas. Puede combinarlo con los filtros de etiquetas descritos anteriormente.

Por ejemplo, la consulta siguiente obtiene todos los elementos de trabajo etiquetados con un {tag}. Devuelve el identificador, el título, el estado y una representación de texto de las etiquetas combinadas.

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

Importante

La propiedad TagNames tiene un límite de longitud de 1024 caracteres. Contiene un conjunto de etiquetas que caben dentro de ese límite. Si un elemento de trabajo tiene muchas etiquetas o las etiquetas son muy largas, TagNames no contenga el conjunto completo y Tag la propiedad de navegación se debe usar en su lugar.

❌ No use tolower y las funciones para realizar la comparación sin distinción entre mayúsculas y toupper minúsculas

Si ha trabajado con otros sistemas, es posible que espere usar las tolower funciones o para la comparación sin distinción entre mayúsculas y toupper minúsculas. Con Analytics, todas las comparaciones de cadenas no distinguen mayúsculas de minúsculas de forma predeterminada, por lo que no es necesario aplicar ninguna función para controlarla explícitamente.

Por ejemplo, la consulta siguiente obtiene todos los elementos de trabajo etiquetados con "QUALITY", "quality" o cualquier otra combinación de mayúsculas y minúsculas de esta palabra.

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

❌ NO use la expansión sin enlazar con $levels=max

OData tiene la capacidad de expandir todos los niveles de una estructura jerárquica. Por ejemplo, el seguimiento de elementos de trabajo tiene algunas entidades en las que se podría aplicar una expansión sin enlazar. Esta operación solo funciona para organizaciones con una pequeña cantidad de datos. No se escala bien para conjuntos de datos más grandes. No lo use en absoluto si:

  • Está trabajando con grandes conjuntos de datos.
  • Está desarrollando un widget y no tiene control sobre dónde se instala el widget.

✔️ Uso de la paginación controlada por servidor

Si solicita que se envíe un conjunto demasiado grande en una sola respuesta, Analytics aplica la paginación. La respuesta incluye solo un conjunto parcial y un vínculo que permite recuperar el siguiente conjunto parcial de elementos. Esta estrategia se describe en la especificación de OData: versión 4.0 de OData. Parte 1: Protocolo: paginación controlada por servidor. Al permitir que el servicio controle la paginación, obtendrá el mejor rendimiento, ya skiptoken que ha sido cuidadosamente diseñado para que cada entidad sea lo más eficaz posible.

El vínculo a la página siguiente se incluye en la @odata.nextLink propiedad .

{
  "@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"}

Nota:

La mayoría de los clientes de OData existentes pueden controlar la paginación controlada por el servidor automáticamente. Por ejemplo, esta estrategia ya la usan las siguientes herramientas: Power BI, SQL Server Integration Services y Azure Data Factory.

❌ NO use $top ni $skip las opciones de consulta para implementar la paginación controlada por el cliente

Con otras API REST, es posible que haya implementado la paginación controlada por el cliente con $top opciones de consulta y $skip . No los use con Analytics. Hay varios problemas con este enfoque y el rendimiento es uno de ellos. En su lugar, adopte la estrategia de paginación controlada por el servidor descrita en la sección anterior.

✔️ $top Use la opción de consulta para limitar el número de registros.

Solo se desaconseja la opción $top de consulta cuando se usa junto con $skip. Si en el escenario de informes solo necesita un subconjunto de registros (por ejemplo, ejemplo), está bien usar $top la opción de consulta. Además, si necesita clasificar los registros según algunos criterios, siempre debe usar $top en combinación con $orderby para obtener un resultado estable con los registros clasificados principales.

✔️ CONSIDERE la posibilidad de escribir una consulta para devolver un número reducido de registros

Escribir una consulta para devolver un número reducido de registros es la guía más intuitiva. Apunte siempre a capturar solo los datos que realmente le interesan. Puede lograrlo haciendo que la mayor parte de las eficaces funcionalidades de filtrado estén disponibles en el lenguaje de consulta OData.

✔️ CONSIDERE la posibilidad de limitar el número de propiedades seleccionadas a un mínimo

Algunos administradores de proyectos personalizan en gran medida sus procesos agregando campos personalizados. La personalización intensiva puede provocar problemas de rendimiento al capturar todas las columnas disponibles en entidades anchas (por ejemplo, WorkItems). El análisis se basa en una tecnología de índice de almacén de columnas. Esto significa que los datos son tanto el almacenamiento como el procesamiento de consultas se basan en columnas. Por lo tanto, cuantos más propiedades haga referencia a una consulta, más caro será procesar. Apunte siempre a limitar el conjunto de propiedades de las consultas a lo que realmente le interesa en el escenario de informes.

✔️ CONSIDERE la posibilidad de filtrar las propiedades de clave suplente de fecha (DateSK sufijo)

Hay muchas maneras de definir un filtro de fecha. Puede filtrar directamente en la propiedad date (por ejemplo, CreatedDate), su homólogo de navegación (por ejemplo, CreatedOnDate) o su representación de clave suplente (por ejemplo, CreatedDate). La última opción produce el mejor rendimiento y se prefiere cuando los requisitos de informes lo permiten.

Por ejemplo, la consulta siguiente obtiene todos los elementos de trabajo creados desde principios de 2020.

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

✔️ CONSIDERE la posibilidad de filtrar las columnas de clave suplente

Si desea filtrar los datos en el valor de un objeto relacionado (por ejemplo, filtrar un elemento de trabajo en el nombre del proyecto), siempre tiene dos opciones. Puede usar la propiedad de navegación (por ejemplo, Project/ProjectName) o capturar la clave suplente por adelantado y usarla directamente en la consulta (por ejemplo, ProjectSK).

Si va a crear un widget, se recomienda usar la última opción. Cuando se pasa la clave como parte de la consulta, se reduce el número de conjuntos de entidades que se deben tocar y el rendimiento mejora.

Por ejemplo, la consulta siguiente filtra WorkItems mediante ProjectSK la propiedad en lugar de Project/ProjectName la propiedad de navegación.

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

❌EVITE el uso de Parentpropiedades , Childreno Revisions en las $filter cláusulas o $expand

Los elementos de trabajo son las entidades más costosas del modelo de datos completo. Tienen varias propiedades de navegación que se pueden usar para acceder a elementos de trabajo relacionados: Parent, Children, Revisions. Sin embargo, cada vez que los use dentro de una consulta, espere un descenso en el rendimiento. Siempre pregunta si realmente necesita una de estas propiedades y puede actualizar el diseño.

Por ejemplo, en lugar de expandir Parent, puede capturar más elementos de trabajo y usar la ParentWorkItemId propiedad para reconstruir la jerarquía completa del lado cliente. Llevar a cabo esta optimización por caso.

✔️ CONSIDERE la posibilidad de pasar VSTS.Analytics.MaxSize la preferencia en el encabezado

Al ejecutar una consulta, no sabe el número de registros que devuelve la consulta. Envíe otra consulta con agregaciones o siga todos los vínculos siguientes y capture todo el conjunto de datos. El análisis respeta las VSTS.Analytics.MaxSize preferencias, lo que le permite producir un error rápido en esas instancias de que el conjunto de datos es mayor que lo que el cliente puede aceptar.

Esta opción es útil en escenarios de exportación de datos. Para usarlo, debe agregar Prefer encabezado a la solicitud HTTP y establecerlo VSTS.Analytics.MaxSize en un valor no negativo. El VSTS.Analytics.MaxSize valor representa el número máximo de registros que puede aceptar. Si se establece en cero, se usa un valor predeterminado de 200 K.

Por ejemplo, la consulta siguiente devuelve elementos de trabajo si el conjunto de datos es menor o igual a 1000 registros.

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}

Si el conjunto de datos supera el límite de 1000 registros, la consulta produce un error inmediatamente con el siguiente error.

El resultado de la consulta contiene 1296 filas y supera el tamaño máximo permitido de 1000. Reduzca el número de registros aplicando filtros adicionales.

Para obtener información sobre cómo establecer el tamaño máximo de página, vea la propiedad ODataPreferenceHeader.MaxPageSize.

Directrices de estilo de consulta

✔️ Use la $count propiedad virtual en los métodos de agregación.

Algunas entidades exponen Count la propiedad . Facilitan algunos escenarios de informes cuando los datos se exportan a un almacenamiento diferente. Sin embargo, no debe usar estas columnas en agregaciones en consultas de OData. Use la $count propiedad virtual en su lugar.

Por ejemplo, la consulta siguiente devuelve el número total de elementos de trabajo.

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

❌ EVITE usar la $count propiedad virtual en el segmento de dirección URL.

Aunque el estándar OData permite usar $count la propiedad virtual para conjuntos de entidades (por ejemplo, _odata/v1.0/WorkItems/$count), no todos los clientes pueden interpretar la respuesta correctamente. Por lo tanto, se recomienda usar agregaciones en su lugar.

Por ejemplo, la consulta siguiente devuelve el número total de elementos de trabajo.

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

✔️ CONSIDERE la posibilidad de usar alias de parámetro para separar partes volátiles de la consulta

Los alias de parámetro proporcionan una solución elegante para extraer elementos volátiles como valores de parámetro del texto de la consulta principal. Puede usarlos en expresiones que evalúen:

  • Valor primitivo
  • Valor complejo
  • Colección de valores primitivos o complejos.

Para obtener más información, vea OData Versión 4.0. Parte 2: Convenciones de dirección URL: alias de parámetro 5.1.1.13. Los parámetros son útiles cuando el texto de la consulta se usa como una plantilla que se puede crear una instancia con los valores proporcionados por el usuario.

Por ejemplo, la consulta siguiente usa @createdDateSK el parámetro para separar el valor de la expresión de filtro.

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

❌ EVITE mezclar $apply y $filter cláusulas en una sola consulta

Si desea agregar filter a la consulta, tiene dos opciones. Puede hacerlo con la $filter cláusula o la $apply=filter() combinación. Cada una de estas opciones funciona bien por sí sola, pero combinarlas puede provocar algunos resultados inesperados.

A pesar de la expectativa que podría tener, OData define claramente un orden de evaluación. Además, la $apply cláusula tiene prioridad sobre $filter. Por este motivo, debe elegir una u otra, pero evitar estas dos opciones de filtro en una sola consulta. Es importante si las consultas se generan automáticamente.

Por ejemplo, la consulta siguiente filtra primero los elementos de trabajo por StoryPoint gt 5, los resultados agregados por son ruta de acceso y, por último, filtra el resultado por StoryPoints gt 2. Con este orden de evaluación, la consulta siempre devuelve un conjunto vacío.

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)
    )

✔️ CONSIDERE la posibilidad de estructurar la consulta para que coincida con el orden de evaluación de OData.

Dado que la combinación y filter las cláusulas de una sola consulta pueden provocar confusión potencial, se recomienda estructurar $apply las cláusulas de consulta para que coincidan con el orden de evaluación.

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

✔️ CONSIDERE la posibilidad de revisar las funcionalidades de OData descritas en las anotaciones de metadatos.

Cuando no está seguro de qué funcionalidades de OData Analytics admite, puede buscar anotaciones en los metadatos. El Comité Técnico del Protocolo de Datos Abiertos (OData) de OASIS en un repositorio tc de GitHub mantiene una lista de anotaciones disponibles.

Por ejemplo, la lista de funciones de filtro admitidas está disponible en Org.OData.Capabilities.V1.FilterFunctions la anotación en el contenedor de entidades.

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

Otra anotación útil es Org.OData.Capabilities.V1.ExpandRestrictions, que explica qué propiedades de navegación no se pueden usar en la $expand cláusula . Por ejemplo, la siguiente anotación explica que Revisions en el WorkItems conjunto de entidades no se puede expandir.

<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>