Propriétés indexées
Dans ThingWorx 9.3 et versions ultérieures, les propriétés peuvent être indexées pour accélérer les requêtes. Cette indexation ne doit être réalisée que sur les propriétés qui ne font pas l'objet de modifications fréquentes. Par exemple, les numéros de modèle, les numéros de série, les villes ou les régions. Lorsque vous demandez leur indexation dans ThingWorx, les valeurs de propriété sont stockées dans le fournisseur de persistance de propriétés, où la base de données se charge de les indexer pour accélérer les requêtes lors de l'utilisation des API QueryImplementingThingsOptimized et QueryImplementingThingsOptimizedCount.
Lorsqu'une requête ne porte que sur des propriétés indexées, elle est uniquement exécutée sous forme de requête de base de données.
Si la requête porte sur un mixte de propriétés indexées et de propriétés non indexées, ThingWorx détermine si le lancement d'une requête indexée présente un avantage, et la déclenche si tel est le cas. Dans ce cas de figure, ThingWorx commence par déclencher cette requête indexée sur la base de données des propriétés pour les champs indexés. Une fois le jeu de résultats correspondant généré, ThingWorx lance une requête sur le cache mémoire pour les propriétés non indexées. A titre d'exemple, imaginons que vous souhaitez interroger tous les objets situés dans une ville particulière (propriété indexée) dont la température (données de télémesure, non indexables) dépasse un certain seuil. ThingWorx commencera dans ce cas par interroger la base de données pour la ville, puis interrogera ensuite le cache mémoire pour les données de télémesure (température).
Dès lors que la requête ne peut pas tirer profit de l'indexation, ThingWorx interroge le cache mémoire.
Bien que les requêtes sur la base de données offrent le plus souvent des performances supérieures, elles seront toutefois parfois meilleures si QueryImplementingThingsOptimized se dispense d'interroger les données d'index. Un cas de figure connu est celui dans lequel la requête sur les données d'index renvoie plus de 80 % du nombre total d'objets dans le modèle. Dans ce cas, ThingWorx intègre une "indication" à la requête pour forcer QueryImplementingThingsOptimized à ne pas utiliser les données d'index et à interroger uniquement le cache mémoire. Pour plus d'informations, consultez les sections Indications et Bonnes pratiques ci-dessous.
L'indexation est prise en charge sur les bases de données PostgreSQL, MS SQL et Azure SQL. Si vous utilisez H2, vous pouvez modéliser et créer votre application sur H2, mais les propriétés ne seront pas indexées et il n'y aura pas de bénéfices en matière de performances avec les API QueryImplementingThingsOptimized et QueryImplementingThingsOptimizedCount.
Cela peut prendre un peu de temps pour que les propriétés indexées soient persistantes dans la base de données après leur création ou leur mise à jour. L'utilisation du service QueryImplementingThingsOptimizedWithTotalCount sur la propriété indexée immédiatement après les mises à jour des propriétés renvoie des résultats incomplets ou inattendus. Réexécutez le service QueryImplementingThingsOptimizedWithTotalCount après 2 secondes pour obtenir les résultats corrects.
Détermination des propriétés à indexer
Tenez compte des éléments suivants pour identifier les propriétés pertinentes à indexer :
L'indexation est limitée aux types de base suivants des propriétés : STRING, NUMBER, INTEGER, LONG, BOOLEAN et tous les types de base stockés en tant que chaînes.
* 
Les types de base suivants sont stockés en tant que chaînes : DATETIME, THINGNAME, USERNAME, GROUPNAME, HYPERLINK, IMAGELINK, MASHUPNAME, MENUNAME, DASHBOARDNAME, TEXT, GUID, NOTIFICATIONCONTENTNAME, NOTIFICATIONDEFINITIONNAME, STYLETHEMENAME et THINGGROUPNAME.
Seules les propriétés dont les valeurs ne sont pas fréquemment modifiées ou qui ne changent pas sont pertinentes à indexer. Les propriétés fréquemment modifiées n'ont pas lieu d'être prises en compte. A titre d'exemple, les numéros de modèle et les numéros de série sont des propriétés pertinentes à indexer. Pour les équipements fixes, la ville, l'Etat ou la région sont également des propriétés qui peuvent être prises en compte.
* 
Les données de télémesure ne doivent jamais être indexées.
La propriété sera-t-elle utilisée lors des appels de QueryImplementingThingsOptimized ? Toutes les propriétés indexées sont également rendues persistantes, de sorte que l'indexation d'une propriété ne se justifie que dès lors qu'un bénéfice effectif en sera retiré. Les propriétés persistantes imposant une surcharge à ThingWorx, il n'y a pas lieu à cet égard d'indexer les propriétés qui ne seront pas utilisées par QueryImplementingThingsOptimized.
Configuration des propriétés indexées
Le paramètre Index est accessible dans la section des propriétés des entités. Pour plus d'informations, consultez la rubrique Propriétés d'objet.
Limites en nombre d'octets pour l'indexation
En raison des restrictions de longueur en octets applicables pour les index, les limites suivantes s'appliquent pour les propriétés de type chaîne :
Les chaînes sont limitées à 1 500 octets avec MS SQL ou Azure SQL comme fournisseur de persistance. Les chaînes sont stockées au format UTF-16 dans MS SQL et Azure SQL.
Les chaînes sont limitées à 1 000 avec PostgreSQL comme fournisseur de persistance. Les chaînes sont stockées au format UTF-8 dans PostgreSQL.
Les valeurs de chaîne qui dépassent la longueur maximale en octets ne sont pas ajoutées à l'index et ne sont pas prises en compte par les requêtes indexées. Dans ce cas, une erreur est ajoutée dans le journal de l'application, indiquant que la valeur était trop grande et non indexée. Bien que la valeur de chaîne ne soit pas indexée, elle sera stockée et rendue persistante. Les API telles que GetPropetyValues pourront toujours récupérer la valeur stockée et celle-ci restera disponible après un redémarrage. Si vous craignez qu'une valeur de chaîne ne puisse dépasser la limite maximale d'octets, il est possible de créer une notification basée sur l'événement de modification de données.
Propriétés par défaut prises en charge
Le tableau suivant répertorie les propriétés qui sont présentes sur tous les objets et qui sont prises en charge par les requêtes sur les données d'index.
Nom de la propriété
Type de propriété
Prend en charge les requêtes indexées ?
name
STRING
oui
description
STRING
oui
tags
TAGS
oui
isSystemObject
BOOLEAN
non
homeMashup
STRING
non
avatar
IMAGE
non
projectName
STRING
non
thingTemplate
STRING
oui
Paramètres d'entrée utilisateur QueryImplementingThingsOptimized
Les opérations suivantes peuvent être déclenchées lors de l'exécution de QueryImplementingThingsOptimized.
Nom de l'opération
Notes
Etats d'optimisation potentiels (si fournis sur la requête et non nuls)
ResultDefinition
Spécifié via les paramètres basicPropertyNames et propertyNames lors de l'appel d'API.
basicPropertyNames : liste des propriétés de base à renvoyer.
propertyNames : liste des propriétés intégrées et propriétés de l'entité d'implémentation à renvoyer.
* 
Si les deux paramètres sont fournis non définis ou nuls sur la requête, toutes les propriétés sont renvoyées dans le résultat. Le renvoi inclut l'ensemble des propriétés de base, des propriétés intégrées et des propriétés définies sur l'entité d'implémentation.
Si toutes les définitions de propriété demandées sont indexées, QueryImplementingThingsOptimized n'interroge que les données d'index pour générer le jeu de résultats.
Si seules certaines des définitions de propriété demandées sont indexées et que l'opération est prise en charge, QueryImplementingThingsOptimized exécute une requête indexée pour les propriétés indexées et utilise le jeu de résultats généré pour interroger le cache mémoire pour les propriétés non indexées.
Si aucune des définitions de propriété demandées n'est indexée ou si un paramètre est NULL, QueryImplementingThingsOptimized interroge le cache mémoire.
NameMask
Modèle de type masque à utiliser pour la mise en correspondance des noms d'objet.
NameMask n'influe en rien sur l'utilisation ou non par QueryImplementingThingsOptimized d'une requête sur les données d'index.
NetworkName
Nom du réseau auquel un objet d'implémentation donné doit appartenir. Des indications peuvent être fournies. Par exemple, vous pouvez spécifier la profondeur de réseau maximale et le nom des réseaux parents afin d'affiner la recherche.
QueryImplementingThingsOptimized interrogera le cache mémoire.
Tags
Liste des tags que doit posséder l'entité pour être incluse dans le résultat.
QueryImplementingThingsOptimized interrogera les données d'index pour les tags.
Offset
Décalage à appliquer pour le premier résultat de la requête, utilisé pour la pagination. Par exemple, si 200 résultats sont trouvés dans la base de données, avec un décalage défini sur 5, les résultats renvoyés seront les résultats 5 à 200 (pour un total de 195 résultats).
Limit n'influe en rien sur l'utilisation ou non par QueryImplementingThingsOptimized d'une requête sur les données d'index.
Sort
Tri à appliquer au résultat final.
Si toutes les propriétés définies dans le tri sont indexées, QueryImplementingThingsOptimized interrogera les données d'index pour générer le jeu de résultats.
Si certaines propriétés définies dans le tri ne sont pas indexées, QueryImplementingThingsOptimized interrogera le cache mémoire.
Query
Filtre à appliquer aux enregistrements de résultats.
Si toutes les définitions de propriété demandées sont indexées, QueryImplementingThingsOptimized n'interrogera que les données d'index pour générer le jeu de résultats.
Si seules certaines des définitions de propriété demandées sont indexées et que l'opération est prise en charge, QueryImplementingThingsOptimized exécutera une requête indexée pour les propriétés indexées et utilisera le jeu de résultats généré pour interroger le cache mémoire pour les propriétés non indexées.
Si aucune des définitions de propriété demandées n'est indexée, QueryImplementingThingsOptimized interrogera le cache en mémoire.
Limit
Nombre maximal d'éléments à inclure dans le résultat.
Limit n'influe en rien sur l'utilisation ou non par QueryImplementingThingsOptimized d'une requête sur les données d'index.
Indications
L'interrogation des données d'index de la base de données peut être désactivée en incluant une indication dans le paramètre de requête de QueryImplementingThingsOptimized.
Indication
Obligatoire ?
Par défaut
Action
optimizationDisabled
non
Non inclus
Si la requête n'est pas spécifiée, que l'indication n'est pas incluse dans la requête ou qu'elle est définie sur "false", QueryImplementingThingsOptimized le comportement sera celui décrit plus haut.
Exemple de requête qui ignorera les données d'index, bien que TT_1_Boolean1 soit pourtant une propriété indexée :
query: {
"optimizationDisabled": true,
"sorts": [
{
"fieldName": "name"
}
],
"filters": {
"type": "EQ",
"fieldName": "TT_1_Boolean1",
"value": true
}
} /* QUERY */ ,
Migration du type de base des propriétés
Vous pouvez modifier le type de base de propriétés existantes. Pour prendre en charge les propriétés indexées, les règles de migration suivantes sont appliquées :
Si la propriété possède une valeur définie, ThingWorx tentera de convertir la valeur de la propriété vers son nouveau type de base. Par exemple, si vous convertissez une propriété de type chaîne dont la valeur est "String123" en un entier, la nouvelle valeur de la propriété sera 123. Inversement, si vous convertissez en chaîne une propriété de type entier de valeur 123, la nouvelle valeur de la propriété sera "123".
Si la valeur de la propriété n'est pas définie et que le nouveau type de base possède une valeur par défaut définie, celle-ci sera utilisée pour toutes les requêtes.
Si la valeur par défaut de la propriété n'est pas définie, ThingWorx utilisera la valeur par défaut de son nouveau type de base. Par exemple, les entiers et autres nombres sont définis sur zéro (0) et les chaînes sont définies sur une chaîne vide ("").
Exemples
Les deux tableaux suivants illustrent le comportement qui sera celui des requêtes s'agissant de l'interrogation des données d'index dans différents cas de figure types. L'exemple de modèle est détaillé dans le premier tableau et les comportements types de QueryImplementingThingsOptimized sont décrits dans le deuxième tableau.
Modèles
Le modèle suivant utilise plusieurs propriétés indexées. Il utilise un modèle d'objet sur lequel deux objets sont basés. Cet héritage peut également être obtenu avec une forme d'objet implémentée par un modèle d'objet.
Nom de l'entité
Type d'entité
Implémente
Nom de la propriété
Type de propriété
Propriété indexée ?
TestThingTemplate1
Modèle d'objet
GenericThing
p1
INTEGER
Oui
p2
STRING
Oui
p3
INTEGER
Non
p4
STRING
Non
TestThing1
Objet
TestThingTemplate1
Hérité
Hérité
Hérité
TestThing2
Objet
TestThingTemplate1
Hérité
Hérité
Hérité
Cas d'optimisation pour QueryImplementingThingsOptimized
Scénario
Exemple
Requête sur les données d'index ?
Commentaires
Toutes les opérations sont prises en charge et le filtre est entièrement pris en charge.
{"sorts":[{"fieldName":"p1"}],"filters":{"type":"And","filters":[{"type":"EQ","fieldName":"p2","value":"12"},
{"type":"EQ","fieldName":"p1","value":"13"}]}}
Oui
Seules des propriétés indexées sont demandées, et ThingWorx interroge donc les données d'index.
Toutes les opérations sont prises en charge et le filtre est partiellement pris en charge.
{"sorts":[{"fieldName":"p1"}],
"filters":{"type":"And","filters":[{"type":"EQ","fieldName":"p4","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
Oui
ThingWorx exécute une requête sur les données d'index pour la propriété P1, puis utilise le jeu de résultats généré pour interroger le cache pour P4.
Toutes les opérations sont prises en charge et le filtre n'est pas pris en charge.
{"sorts":[{"fieldName":"p1"}],"filters":
{"type":"Or","filters":[{"type":"EQ","fieldName":"p4","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
Non
ThingWorx n'interroge que le cache du fait du filtre OU, qui fait qu'une requête sur les données d'index n'apporterait aucun bénéfice.
Toutes les opérations sont prises en charge, aucun filtre n'est fourni.
{"sorts":[{"fieldName":"p1"}]}
Non
Il n'y a rien à filtrer, ThingWorx n'exécute donc pas de requête.
Certaines opérations sont prises en charge et le filtre est entièrement pris en charge.
{"sorts":[{"fieldName":"p4"}],"filters":{"type":"And","filters":
[{"type":"EQ","fieldName":"p2","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
Oui
Tous les champs filtrés sont indexés, et ThingWorx interroge donc les données d'index.
Certaines opérations sont prises en charge et le filtre est partiellement pris en charge.
{"sorts":[{"fieldName":"p4"}],"filters":{"type":"And","filters":
[{"type":"EQ","fieldName":"p4","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
Oui
Même situation qu'à la ligne 2, excepté que le tri porte sur une propriété non indexée.
Certaines opérations sont prises en charge et le filtre n'est pas pris en charge.
{"sorts":[{"fieldName":"p4"}],"filters":{"type":"Or","filters":[{"type":"EQ","fieldName":"p4","value":"12"},
{"type":"EQ","fieldName":"p1","value":"13"}]}}
Non
Le filtre est le même qu'à la ligne 3, de sorte que les requêtes sur les données d'index ne sont pas prises en charge dans ce cas de figure.
Certaines opérations sont prises en charge, aucun filtre n'est fourni.
{"sorts":[{"fieldName":"p4"}]}
Non
Il n'y a rien à filtrer, ce cas de figure n'est donc pas pris en charge.
Des tags sont demandés, aucun filtre n'est fourni.
Oui
Les requêtes sur les tags sont prises en charge pour l'interrogation des données d'index.
Bonnes pratiques
Testez les performances de votre application pour déterminer s'il est préférable de désactiver les optimisations sur les requêtes dans votre cas d'utilisation particulier.
Les requêtes sur les données d'index sont plus performantes lorsqu'elles renvoient un petit sous-ensemble du modèle. Le gain de performance obtenu est le plus sensible lorsque la requête porte sur seul objet. (interrogation par exemple d'un objet unique par son numéro de série).
Si une requête renvoie 80 % ou plus du modèle, utilisez une indication pour désactiver l'interrogation des données d'index.
Le fait de modifier le type de base des propriétés est une opération coûteuse, étant donné que la modification au niveau du modèle d'objet ou de la forme d'objet doit ensuite être propagée à toutes les entités d'implémentation. Sur un grand modèle, l'opération pourra prendre du temps et consommer beaucoup de ressources.
Evitez de modifier des types de base de propriété alors que le système exécute une ingestion.
Assurez-vous que la valeur Taille max. de la file d'attente du fournisseur de persistance est suffisamment élevée pour absorber le nombre d'écritures de propriétés persistantes qui se produiront lors de l'ajout de vos propriétés indexées ou de la modification du type de base de propriétés indexées. La taille maximale de la file d'attente doit être supérieure au nombre d'écritures de propriétés. Le nombre d'écritures sera égal au nombre de propriétés modifiées multiplié par le nombre d'objets implémentant la propriété. Prenons par exemple le cas d'un modèle d'objet implémenté par 10 000 objets. Si vous modifiez le type de base de deux propriétés sur ce modèle d'objet, vous générerez 20 000 écritures (2 propriétés x 10 000 objets) dans la file d'attente d'écriture des propriétés persistantes. La taille maximale de la file d'attente est par défaut de 100 000 écritures, et vous disposerez donc dans cet exemple de ressources suffisantes pour l'opération.
Est-ce que cela a été utile ?