Cassandra Indexing: The Good, The Bad and The Ugly

binnen NoSQL zijn de bewerkingen van het indexeren, ophalen en zoeken naar informatie nauw verbonden met de fysieke opslagmechanismen. Het is belangrijk om te onthouden dat rijen worden opgeslagen op verschillende hosts, maar een enkele rij wordt opgeslagen op een enkele host. (met replica ‘ s) Kolomfamilies worden opgeslagen in gesorteerde volgorde, wat het opvragen van een reeks kolommen efficiënt maakt (mits u rijen overspant).

Het Slechte : Partitionering

een van de moeilijke dingen om aan te wennen op het eerste is dat zonder indexen query ‘ s die rijen overspannen (zeer) slecht kan zijn. Terugdenkend aan ons opslagmodel is dat echter niet verwonderlijk. De strategie die Cassandra gebruikt om de rijen over hosts te verdelen heet partitioneren.

partitioneren is de handeling van het uitsnijden van het bereik van rowkeys toewijzen aan de” token ring”, die ook de verantwoordelijkheid voor een segment (dat wil zeggen partitie) van de RowKey bereik aan elke host toewijst. Je hebt dit waarschijnlijk gezien toen je je cluster initialiseerde met een “token”. Het token geeft de host een locatie langs de token ring, die de verantwoordelijkheid voor een deel van het token bereik toewijst. Partitioneren is de handeling van het toewijzen van de rowkey in het token bereik.

er zijn twee primaire partitioners: Random en Order behoud. Ze hebben een passende naam. De RandomPartitioner hashes de rowkeys in tokens. Met de RandomPartitioner is het token een hash van de rowkey. Dit doet een goed werk van gelijkmatig verdelen van uw gegevens over een set van knooppunten, maar maakt het opvragen van een bereik van de rowkey ruimte ongelooflijk moeilijk. Van alleen een “start rowkey” waarde en een “end rowkey” waarde, Cassandra kan niet bepalen welk bereik van de token ruimte die u nodig hebt. Het moet in wezen een “table scan” uitvoeren om de query te beantwoorden, en een “table scan” in Cassandra is slecht omdat het naar elke machine moet gaan (waarschijnlijk alle machines als je een goede hash-functie hebt) om de query te beantwoorden.

nu, tegen de grote kosten van een gelijkmatige gegevensdistributie, kunt u de Orderreservingpartitioner (OPP) gebruiken. Ik ben *niet* down met OPP. De OPP behoudt orde als het vertaalt rowkeys in tokens. Nu, gegeven een start rowkey waarde en een end rowkey waarde, kan Cassandra * * precies bepalen welke hosts de gegevens hebben die u zoekt. Het berekent de startwaarde naar een token de eindwaarde naar een token, en selecteert en retourneert alles tussen. Maar, door het behoud van de orde, tenzij uw rowkeys zijn gelijkmatig verdeeld over de ruimte, uw tokens zal niet een van beide en je krijgt een scheef cluster, die sterk verhoogt de kosten van de configuratie en het beheer van de cluster. (niet de moeite waard)

de Goede : secundaire indexen

Cassandra biedt een native indexeringsmechanisme in secundaire indexen. Secundaire indexen werken af van de kolommen waarden. Je declareert een secundaire index op een Kolomfamilie. Datastax heeft goede documentatie over het gebruik. Onder de motorkap, Cassandra onderhoudt een “verborgen kolom familie” als de index. (Zie ed Anuff ‘ s presentatie voor details) aangezien Cassandra geen kolomwaarde-informatie in een knooppunt onderhoudt, en secundaire indexen op kolomwaarde staan (in plaats van rowkeys), moet een query nog steeds naar alle knooppunten worden verzonden. Daarnaast worden secundaire indexen niet aanbevolen voor sets met een hoge kardinaliteit. Ik heb nog niet gekeken, maar ik neem aan dat dit komt door het datamodel dat wordt gebruikt binnen de “verborgen kolom familie”. Als de verborgen kolomfamilie een Rij per unieke waarde opslaat (met rowkeys als kolommen), betekent dit dat de rijen moeten worden gescand om te bepalen of ze binnen het bereik in de query liggen.
uit de presentatie van Ed:

  • niet aanbevolen voor hoge kardinaliteitswaarden (dat wil zeggen tijdstempels,geboortedata,trefwoorden,enz.)
  • vereist ten minste één gelijkheidsvergelijking in een query–niet geweldig voor minder-dan/groter-dan/range queries
  • Ongesorteerde resultaten zijn in tokenvolgorde, geen query-waardevolgorde
  • beperkt tot zoeken op datatypes, begrijpt Cassandra native

met dat alles gezegd, secundaire indexen werken uit de doos en we hebben goed succes met behulp van hen op eenvoudige waarden.

het lelijke: Doe-het-zelf (DIY) / brede rijen

nu, schoonheid is in het oog van de toeschouwer. Een van de mooie dingen over NoSQL is de eenvoud. De constructies zijn eenvoudig: Keyspaces, Kolomfamilies, rijen en kolommen. Het houden van het eenvoudig betekent echter soms moet je dingen in eigen handen te nemen.

Dit is het geval bij indexen met brede rijen. Met behulp van Cassandra ‘ s storage model, zijn gemakkelijk om uw eigen indexen te bouwen waar elke rij-toets wordt een kolom in de index. Dit is soms moeilijk om je hoofd rond te krijgen, maar laten we ons voorstellen dat we een geval hebben waarbij we alle gebruikers in een Postcode willen selecteren. De belangrijkste gebruikers kolom familie is ingetoetst op userid, postcode is een kolom op elke gebruikers rij. We kunnen secundaire indexen gebruiken, maar er zijn nogal wat postcodes. In plaats daarvan zouden we een kolomfamilie kunnen onderhouden met een enkele rij genaamd “idx_zipcode”. We kunnen dan kolommen schrijven in deze rij van het formulier “zipcode_userid”. Aangezien de kolommen in gesorteerde volgorde worden opgeslagen, is het snel om alle kolommen te bevragen die beginnen met” 18964 ” (we zouden bijvoorbeeld 18964_ en 18964_ZZZZZZ als begin-en eindwaarden kunnen gebruiken).

een duidelijk nadeel van deze aanpak is dat rijen op zichzelf staan op een host. (nogmaals, behalve voor replica ‘s) dit betekent dat alle query’ s gaan om een enkele knooppunt te raken. Ik heb hier nog geen goed antwoord op gevonden.

bovendien, en IMHO, het lelijkste deel van DIY brede rij indexering is vanuit een client perspectief. In onze implementatie hebben we ons best gedaan om taalagnostisch te zijn aan de kant van de klant, zodat mensen de beste tool kunnen kiezen voor de taak om te communiceren met de gegevens in Cassandra. Met die mentaliteit geven de doe-het-zelfindexen wat problemen. Wide-rows gebruiken vaak samengestelde toetsen(stel je voor dat je een idx_state_zip had, die je in staat zou stellen om te query op staat dan zip). Hoewel er “native” ondersteuning is voor samengestelde sleutels, implementeren alle clientbibliotheken hun eigen versie ervan (Hector, Astyanax en Thrift). Dit betekent dat de client die gegevens moet opvragen de toegevoegde logica moet hebben om eerst de index te bevragen, en bovendien moeten alle clients de samengestelde sleutel op dezelfde manier construeren.

Om Het Beter Te Maken…

om deze reden hebben we besloten om twee open source projecten vrij te geven die helpen deze logica naar de server-kant te pushen. Het eerste project is Cassandra-Triggers. Hiermee kunt u asynchrone activiteiten toevoegen aan schrijft in Cassandra. (een dergelijke activiteit zou kunnen indexeren) we hebben ook vrijgegeven Cassandra-indexeren. Dit is heet van de persen en staat nog in de kinderschoenen (het ondersteunt bijvoorbeeld alleen UT8Types in de index), maar de bedoeling is om een generiek server-side mechanisme aan te bieden dat gegevens indexeert zoals het naar Cassandra geschreven is. Gebruikmakend van dezelfde server-side techniek die we gebruikten in Cassandra-Indexing, configureer je eenvoudig de kolommen die je wilt indexeren, en de AOP code doet de rest als je naar het doel CF schrijft. Zoals altijd zijn vragen, opmerkingen en gedachten welkom. (vooral als ik ergens buiten de basis ben)

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.