6
votes

Comment accélérer une requête agrégée Cosmos DB?

Notre requête agrégée cosmos db semble lente et coûte beaucoup de RU. Voici les détails (plus voir capture d'écran ci-dessous): 2.4s et 3222RU pour compter un jeu de résultats de 414k enregistrements. Aussi ceci pour un seul compte. Normalement, nous voudrions faire une somme sur plusieurs champs à la fois (possible uniquement dans une seule partition), mais les performances sont bien pires.

 cosmos db query

Il y a 2 millions d'enregistrements dans cette collection. Nous utilisons Cosmos DB avec API SQL. Cette collection particulière est partitionnée par country_code et il y a 414 732 enregistrements en France («FR») et le reste aux États-Unis. La taille du document est en moyenne de 917 octets et peut-être min est de 800 octets, max 1300 octets.

Notez que nous avons également essayé une clé de partitionnement beaucoup plus clairsemée comme device_id (dont il y en a 2 millions, 1 doc par périphérique ici) qui donne de pires résultats pour cette requête. Le champ c.calcuated.flag1 représente simplement un "état" dont nous voulons garder un décompte (nous avons en fait 8 états sur lesquels j'aimerais résumer).

L'indexation sur cette collection est la valeur par défaut, qui utilise le mode d'index "cohérent" et indexe tous les champs (et inclut des index de plage pour Number et String). Le paramètre RU est à 20 000 et il n'y a aucune autre activité dans la base de données.

Alors faites-moi savoir ce que vous en pensez. Cosmos DB peut-il être utilisé raisonnablement pour obtenir quelques sommes ou décomptes sur les champs sans augmenter nos charges RU et prendre beaucoup de temps? Bien que la 2.4s ne soit pas terrible, nous avons vraiment besoin de requêtes en moins d'une seconde pour ce genre de chose. Notre application (basée sur l'IoT) a souvent besoin de documents individuels, mais aussi parfois de ce type de décompte pour tous les documents d'un pays.

Existe-t-il un moyen d'améliorer les performances?


1 commentaires

Un seul index sur "tous les champs" ne serait pas utile à moins que vous ne filtriez dans l'ordre dans lequel les champs sont répertoriés dans l'index. En supposant que vos deux champs faisaient tous deux partie de l'enregistrement, cela signifierait que vous auriez besoin d'un index sur (country_code, calculé.flag1) . Je suppose du nom que calculé.flag1 est une valeur calculée et non stockée dans la table. Comment cela est-il calculé? L'écriture du calcul dans votre requête peut lui permettre d'utiliser des index.


3 Réponses :


0
votes

Pour la requête spécifique affichée, il n'est pas nécessaire de spécifier le nom de la table et vous pouvez essayer de limiter 1 , certaines performances seront améliorées. Par exemple:

SELECT COUNT (1) FROM c WHERE country_code = "FR" AND added.flag = 1 LIMIT 1

Aussi, n'oubliez pas d ' analyser soigneusement l'exécution de votre requête, je ne suis pas sûr dans Cosmos, mais comme l'approche PostreSQL, EXPLAIN ANALYZE . Assurez-vous également que vous utilisez le meilleur type de variables , par exemple, varchar (2) au lieu de varchar (3). Je recommanderais de changer les types de caractères des pays par nombre , si vous les filtrez (comme vous le faites remarquer). Par exemple, FR = 1, GR = 2 et ainsi de suite. Cela améliorera également les performances. Enfin, si le code du pays et l'indicateur calculé sont liés, créez une variable unique les définissant. Si rien de tout cela ne fonctionne, vérifiez les performances du client, et même le matériel.


0 commentaires

0
votes

Deux idées:

Essayez d'exécuter ce qui suit, voyez si vous obtenez des durées d'exécution différentes:

{  
        "automatic":true,
        "indexingMode":"Consistent",
        "includedPaths":[  
            {  
                "path":"/*"
            }
        ],
        "excludedPaths":[  

        ],
        "compositeIndexes":[  
            [  
                {  
                    "path":"/country_code",
                    "order":"ascending"
                },
                {  
                    "path":"/calculated",
                    "order":"descending"
                }
            ]
        ]
    }

Important! Le Le champ calculé.flag1 , s'il n'est pas persistant, pourrait donner le problème - comme pour chaque document / enregistrement - le moteur de base de données doit calculer le résultat, d'où le RU élevé. Pouvez-vous optimiser les champs calculés? (les décomposer, ou faire le calcul dans le cadre de la requête?)

La deuxième suggestion serait d'essayer de vous faire définir un index composite

SELECT COUNT(1) FROM c WHERE country_code="FR"

Veuillez également consulter Exemples de stratégie d'indexation composite

Et Gérez les stratégies d'indexation dans Azure Cosmos DB pour voir où vous le modifiez


1 commentaires

Merci. Je vais certainement vérifier cela. Cependant, puisque Cosmos a maintenant considérablement amélioré les performances (voir ma réponse publiée), je suppose que le problème était vraiment de leur côté pour commencer. Votre réponse peut effectivement aider, je vous le ferai savoir. Je sais que les index composites sont nécessaires pour faire un "ordre par" multi-colonnes, une fonctionnalité qu'ils viennent de déployer.



1
votes

L'équipe Cosmos DB a maintenant apporté des modifications importantes aux performances d'agrégation et à l'utilisation des index. Il s'agit de leur stratégie d'indexation "v2" et n'a été déployée que récemment (elle n'est peut-être pas encore disponible pour tous les comptes, contactez MSFT si vous avez une ancienne base de données qui doit être mise à jour).

Vous pouvez comparer les nouveaux résultats à l'image que j'ai publiée à l'origine.

Vous noterez maintenant que le temps de chargement du document est de 0 ms et que la taille du document récupéré est de 0 octet. Le temps de chargement que je peux confirmer est vraiment assez rapide maintenant, il est donc possible qu'il soit inférieur à 1 ms lorsqu'il est mesuré du côté serveur. Et une taille de document de 0 a plus de sens car aucun document n'a besoin d'être récupéré pour cela (compte uniquement en fonction de l'index).

Enfin, vous pouvez voir que les RU sont passées de 3222 à 7,4 !!!! Une différence assez drastique.

La somme sur plusieurs colonnes à la fois dans une seule partition est également assez performante maintenant et nous pouvons faire environ 8 sommes à la fois sur 2 millions de documents avec ~ 50 RU et cela prend environ 20 à 70 ms lorsque mesuré à partir d'un point de terminaison d'API de fonction ( inclut donc l'heure du réseau).

L'équipe Cosmos DB a encore du travail à faire pour permettre des agrégations multi-colonnes entre partitions, mais les améliorations que nous avons actuellement sont assez prometteuses.

 entrez la description de l'image ici


2 commentaires

Au-delà de l'amélioration des performances, comment savoir si vous êtes sur une stratégie d'indexation "v2"?


Existe-t-il un document officiel pour fournir cela.