Pourquoi Cassandra déconseille-t-elle de créer un index sur des colonnes à cardinalité élevée?

10

La documentation de Cassandra déclare,

N'utilisez pas d'index dans ces situations:

  • Sur les colonnes à cardinalité élevée, car vous interrogez ensuite un énorme volume d'enregistrements pour un petit nombre de résultats. Voir Problèmes d'utilisation d'un index de colonne à cardinalité élevée ci-dessous.

Ça continue,

Si vous créez un index sur une colonne à cardinalité élevée, qui a de nombreuses valeurs distinctes, une requête entre les champs entraînera de nombreuses recherches pour très peu de résultats. Dans le tableau avec un milliard de chansons, rechercher des chansons par auteur (une valeur généralement unique pour chaque chanson) plutôt que par leur artiste, est susceptible d'être très inefficace. Il serait probablement plus efficace de maintenir manuellement la table sous la forme d'un index au lieu d'utiliser l'index intégré de Cassandra. Pour les colonnes contenant des données uniques, il est parfois judicieux, en termes de performances, d'utiliser un index pour plus de commodité, tant que le volume de requête vers la table ayant une colonne indexée est modéré et n'est pas sous une charge constante.

Mais ne répond jamais vraiment à la question: pourquoi est-il inefficace? Je n'ai aucune idée de ce que signifie "le maintien manuel de la table comme une forme d'index". Mais ensuite, il se contredit quelque peu avec "... il est parfois très judicieux d'utiliser un index pour des raisons de commodité tant que le volume de la requête est modéré ..."

Est-ce juste essayer de me dire d'utiliser le PK quand et où je peux? Quelle est l'inefficacité? D'après ce que je comprends, une requête qui atteindrait un index devrait interroger tous les nœuds du cluster, puis chaque nœud ferait une recherche dans son index local et les résultats seraient ensuite agrégés. Ce n'est pas nécessairement cher (chaque recherche d'index doit être assez bon marché) sauf que nous payons en latence réseau, car nous devons attendre le nœud le plus lent du lot. Suis-je en train de manquer quelque chose ici?

Mais si j'ai une collection qui a un bajillion d'articles qui - en de rares occasions - doivent être recherchés par un attribut différent mais presque unique… c'est une utilisation appropriée, non?

¹Tout? IDK si la réplication signifie que cela peut toucher 1/3 du cluster pour un facteur de réplication de 3 ou non?

Thanatos
la source

Réponses:

6

Avec un index Cassandra ( c'est-à - dire un "index secondaire", par opposition aux clés primaires), chaque nœud doit interroger ses propres données locales pour répondre à une requête (voir la FAQ Cassexra indexexes secondaires ). Ces index sont également construits à l' aide d'un processus d'arrière-plan . Cette mise en contexte signifie que l'indice peut renvoyer de faux négatifs en termes de succès (ou de faux positifs en termes de manquements).

Cela signifie que dans une colonne à cardinalité élevée, le taux de changement ( c'est-à-dire les ajouts / suppressions) de cette colonne peut être assez élevé. Et donc si ce taux de changement est plus rapide que la mise à jour de l'index via le processus d'arrière-plan, alors l'utilisation d'un index est "inefficace" (l'index effectue plus de travail que ce qui est requis par l'application, ce qui peut souvent obtenir la mauvaise réponse) .

Une approche plus efficace , en termes de précision des requêtes , pourrait être de maintenir une deuxième table , plutôt qu'un index secondaire. Les tables, par opposition aux index , sont traitées comme n'importe quelle autre table. Ils sont plus susceptibles de donner à votre application les résultats de requête attendus . L'inconvénient est que le maintien d'une table en tant qu'index , par rapport à un "index secondaire" Cassandra, sont désormais des contraintes d'application ( c'est -à- dire que votre code d'application doit maintenant savoir insérer / supprimer des lignes de cette table "d'index", et pour synchroniser les deux tables via la "réconciliation" au niveau de l'application).

J'espère que cela t'aides!

Castaglia
la source
Que les index soient construits à l'aide d'un processus d'arrière-plan est un peu… moche. Les faux positifs sont visibles pour l'utilisateur, je présume? (Je ne vois pas comment ils ne seraient pas.) La seule partie que je me pose encore est de savoir où vous dites: "Cela signifie que dans une colonne à cardinalité élevée, le taux de changement (c'est-à-dire les ajouts / suppressions) de cette colonne peut être assez élevé. " - Je comprends pourquoi le taux de changement, par rapport à la construction de l'indice bg, serait mauvais, mais je ne vois toujours pas ce que la cardinalité élevée a à voir avec cela. (Sûrement, même une colonne à faible cardinalité subirait le même sort, non?)
Thanatos
Oui, une colonne à faible cardinalité subirait le même sort. J'avoue que ma pensée était un peu floue. Je supposais qu'un indice de cardinalité élevé serait plus susceptible d'avoir un taux de changement plus élevé (donc plus susceptible de présenter des résultats faussement positifs / négatifs); c'est le taux de changement (par rapport au processus d'indexation en arrière-plan) qui est le plus pertinent, pas la cardinalité.
Castaglia
2

Quelques terminologies: la table parent est la table sur laquelle un index est créé. La table d'index secondaire est la table créée pour maintenir un index sur une autre table.

Les données de la table d'index secondaire sont stockées sur le même nœud que les données de la table parent. Le partitionneur Cassandra ne partitionne pas et ne distribue pas les données de la table d'index. Donc, si vous souhaitez effectuer une recherche sur une colonne d'index, tous les nœuds sont interrogés, pas seulement les nœuds de réplique contenant les données. (le nœud coordinateur ne sait pas où résident les données) https://www.datastax.com/dev/blog/cassandra-native-secondary-index-deep-dive

Pour les colonnes à cardinalité élevée telles que ssn ou tout autre identifiant unique, il y aura un mappage un à un avec la clé primaire. Si vous créez un index sur une telle colonne, les données résident sur le nombre de facteurs de réplication des nœuds, mais l'appel de recherche est exécuté sur tous les nœuds. Dans le meilleur des cas, le coordinateur frappe directement les nœuds qui contiennent des données et Une fois le niveau de cohérence atteint, vous obtenez votre résultat. Pire, si les données que vous recherchez ne sont pas présentes dans l'index, vous attendez que tous les nœuds répondent pour constater que les données ne s'y trouvent pas. Ainsi, pour chaque appel de recherche sur une table d'index secondaire, tous les nœuds sont touchés. Comparez cela avec seulement le nombre de nœuds de facteur de réplication touchés pour chaque appel de recherche, au cas où la table est une table C * normale.

Pramod Sivaraju
la source