web-dev-qa-db-fra.com

Où et ordre par clauses dans Cassandra CQL

Je suis nouveau dans la base de données NoSQL et viens de commencer à utiliser Apache Cassandra. J'ai créé un tableau simple "emp" avec la clé primaire sur la colonne "empno". Ceci est un tableau simple car nous obtenons toujours le schéma scott par défaut d'Oracle.

À présent, j'ai chargé des données à l'aide de la commande COPY et émis la requête Select * from emp order by empno, mais j'ai été surpris de constater que CQL n'autorisait pas l'option Order by sur la colonne empno (qui correspond à PK). De même, lorsque j'ai utilisé la condition Where, elle ne permettait aucune opération d'inégalité sur la colonne empno (seule la condition EQ ou IN était autorisée). De plus, il ne permettait pas de placer Where et Order sur une autre colonne, car ils n'étaient pas utilisés dans PK et n'avaient pas d'index.

Quelqu'un peut-il m'aider s'il vous plaît, que dois-je faire si je veux que empno soit unique dans le tableau et que les résultats de la requête soient dans l'ordre trié de empno?

(Ma version est: 

cqlsh:demodb> show version [cqlsh 5.0.1 | Cassandra 2.2.0 | CQL spec 3.3.0 | Native protocol v4])

8
Amir S Siddiqui

Une clé primaire en Cassandre se compose de deux parties:

  • clé (s) de partition
  • clé de regroupement

PRIMARY KEY (partitionKey1,clusteringKey1,clusteringKey2)

ou

PRIMARY KEY ((partitionKey1,partitionKey2),clusteringKey1,clusteringKey2)

La clé de partition détermine le ou les nœuds sur lesquels vos données sont stockées. La clé de cluster détermine l'ordre des données dans votre clé de partition.

Dans CQL, la clause ORDER BY est réellement utilisée uniquement pour inverser le sens de tri défini de votre ordre de mise en cluster. En ce qui concerne les colonnes elles-mêmes, vous pouvez uniquement spécifier les colonnes définies (et dans cet ordre exact ... pas d'ignorance) dans votre clause CLUSTERING ORDER BY au moment de la création de la table. Vous ne pouvez donc pas choisir des colonnes arbitraires pour ordonner votre jeu de résultats au moment de la requête.

Cassandra obtient des performances optimales en utilisant les clés de regroupement pour trier vos données sur disque, renvoyant ainsi uniquement les lignes ordonnées en une seule lecture (aucune lecture aléatoire). C'est pourquoi vous devez adopter une approche de modélisation basée sur une requête (dupliquant souvent vos données dans plusieurs tables de requête) avec Cassandra. Connaissez vos requêtes à l'avance et construisez vos tables pour les servir.

Select * from emp order by empno;

Tout d’abord, vous avez besoin d’une clause WHERE. Vous pouvez interroger sans elle, si vous travaillez avec une base de données relationnelle. Avec Cassandra, vous devez faire de votre mieux pour éviter les requêtes non liées SELECT. De plus, Cassandra ne peut appliquer qu'un ordre de tri au sein d'une partition. Par conséquent, les requêtes sans clause WHERE ne renverront pas les données dans l'ordre de votre choix.

Deuxièmement, comme je l’ai mentionné ci-dessus, vous devez définir des clés de clustering. Si vous souhaitez classer votre résultat par empno, vous devez trouver une autre colonne à définir comme clé de partition. Essayez quelque chose comme ça:

CREATE TABLE emp_by_dept (
  empno text,
  dept text,
  name text,
  PRIMARY KEY (dept,empno)
) WITH CLUSTERING ORDER BY (empno ASC);

Maintenant, je peux interroger des employés par département, et ils me seront retournés par ordre de empno:

SELECT * FROM emp_by_dept WHERE dept='IT';

Mais pour être clair, vous not pourrez interroger chaque ligne de votre table et la faire classer par une seule colonne. La seule façon d'obtenir un ordre significatif dans vos ensembles de résultats consiste à tout d'abord partitionner vos données de manière cohérente pour votre analyse de rentabilisation. L'exécution d'une SELECT non liée renverra toutes vos lignes (en supposant que la requête n'expire pas en essayant d'interroger tous les nœuds de votre cluster), mais que l'ordre des ensembles de résultats ne peut être appliqué qu'au sein d'une partition. Il faut donc restreindre par clé de partition pour que cela ait un sens.

Mes excuses pour l'auto-promotion, mais l'année dernière, j'ai écrit un article pour DataStax intitulé We Shall Have Order! , dans lequel j'ai abordé la façon de résoudre ce type de problèmes. Donnez-lui une lecture et voyez si cela aide.

Modifier pour des questions supplémentaires:

De votre réponse, j'ai conclu 2 choses à propos de Cassandra: 

(1) Il n’existe pas de moyen D’obtenir un ensemble de résultats qui est uniquement ordonné par une colonne qui a été définie comme Comme unique.

(2) Lorsque nous définissons une PK (Clé de partition + clé de clustering), le résultat sera toujours ordre en regroupant des colonnes dans une clé de partition fixe (nous devons limiter à une valeur de clé de partition), cela signifie qu'il n'est pas nécessaire d'utiliser la clause ORDER BY , car elle ne peut jamais modifier l'ordre des lignes (l'ordre dans , quelles lignes sont réellement stockées) , ie Order By est inutile.

1) Toutes les clés principales de Cassandra sont uniques. Il n'y a aucun moyen de commander votre résultat défini par votre clé de partition. Dans mon exemple, je commande par empno (après partitionnement par département). - Aaron Il y a 1 heure 

2) Sans vouloir dire que ORDER BY est inutile, je dirai que son seul véritable usage est de changer le sens du tri entre ASC et DESC.

J'ai créé un index sur la colonne "empno" de la table "emp", elle ne permet toujours pas Permettant ORDER BY empno. Alors, à quoi servent les index? S'agit-il uniquement de recherches d'enregistrements pour une valeur spécifique de la clé d'index?

Vous ne pouvez pas commander un jeu de résultats dans une colonne indexée. Les index secondaires sont (pas les mêmes que leurs homologues relationnels) vraiment utiles uniquement pour les requêtes Edge-case, basées sur l'analyse. Comme ils ne sont pas à l'échelle, la recommandation générale est de ne pas utiliser d'index secondaires.

Ok, cela signifie simplement qu’une table ne peut pas être utilisée pour obtenir Différents ensembles de résultats avec des conditions différentes et un ordre de tri différent .

Correct.

Par conséquent, pour chaque nouvelle exigence, nous devons créer une nouvelle table. IT signifie que si nous avons un milliard de lignes dans une table (par exemple une table Sales) et que Nous avons besoin de la somme des ventes (1). Produit, deux (2) régions, nous dupliquerons tous ces milliards de lignes dans deux tableaux, l’un en ordre de regroupement De Produit, l’autre en ordre de regroupement de Région ,. et même si nous devons additionner les ventes par Salesman_id, nous construisons une troisième table, mettant à nouveau tous ces milliards de lignes? est-ce raisonnable?

C'est vraiment à vous de décider à quel point c'est raisonnable. Mais le manque de flexibilité des requêtes est un inconvénient de Cassandra. Pour contourner ce problème, vous pouvez continuer à créer des tables de requête (I.E., disque commercial pour la performance). Mais si le problème devient trop difficile à gérer, il est temps de réfléchir à la question de savoir si Cassandra est vraiment la bonne solution.

EDIT 20160321

Bonjour Aaron, vous avez dit plus haut: "N'arrêtez pas de dire que ORDER BY est inutile, je dirai que son seul véritable usage est de changer le sens du tri entre ASC et DESC."

Mais j'ai trouvé même que ce n'est pas correct. Cassandra n'autorise que ORDER par dans le même sens que celui défini dans le calque "CLUSTERING ORDER BY" de CREATE TABLE. Si dans cette clause nous définissons ASC, il ne permet que l'ordre par ASC, et inversement.

Sans voir de message d'erreur, il est difficile de savoir quoi vous dire à ce sujet. Bien que j'ai entendu parler de requêtes avec ORDER BY échouant lorsque vous avez trop de lignes stockées dans une partition.

ORDER BY fonctionne également un peu bizarre si vous spécifiez plusieurs colonnes à trier. Si deux colonnes de clustering sont définies, je peux utiliser ORDER BY sans distinction dans la première colonne. Mais dès que j'ajoute la deuxième colonne à la clause ORDER BY, ma requête ne fonctionne que si je spécifie les deux directions de tri identiques (en tant que définition CLUSTERING ORDER BY) ou les deux différentes. Si je mélange et correspond, je reçois ceci:

InvalidRequest: code=2200 [Invalid query] message="Unsupported order by relation"

Je pense que cela a à voir avec la façon dont les données sont stockées sur le disque. Sinon, Cassandra aurait plus de travail à faire pour préparer les jeux de résultats. Alors que s’il faut que tout soit en correspondance ou en miroir avec la ou les directions spécifiées dans le CLUSTERING ORDER BY, il ne peut que relayer une lecture séquentielle à partir du disque. Il est donc probablement préférable d’utiliser une seule colonne dans votre clause ORDER BY pour obtenir des résultats plus prévisibles.

16
Aaron

L'ajout d'une réponse redux comme réponse acceptée est assez long.

L'ordre par n'est actuellement pris en charge que sur les colonnes en cluster de PRIMARY KEY Et lorsque la clé de partition est restreinte par une clause Equality ou un opérateur IN dans la clause where.

C’est-à-dire si votre clé primaire est définie comme ceci:

PRIMARY KEY ((a,b),c,d)

Ensuite, vous pourrez utiliser ORDER BY when & only quand votre requête a:

une clause where avec toute la clé primaire restreinte par un opérateur d'égalité (=) ou un opérateur IN tel que: 

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c,d;

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY c;

Ces deux requêtes sont les seules valides.

Aussi cette requête ne fonctionnerait pas:

SELECT * FROM emp WHERE a = 1 AND b = 'India' ORDER BY d,c;

car order by ne prend actuellement en charge que le classement des colonnes suivant leur ordre déclaré dans la clé primaire qui est dans la définition de clé primaire c a été déclaré avant d et la requête viole le classement en plaçant d en premier.

0
Sankar