select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
hvordan ovenstående forespørgsel vil fungere internt i cassandra?
i det væsentlige vil alle data for partitionscopeid=35
ogformid=78005
blive returneret og derefter filtreret afrecord_link_id
indeks. Det vil se efterrecord_link_id
post for9897
og forsøge at matche poster, der matcher rækkerne, der returneres, hvorscopeid=35
ogformid=78005
. Krydset mellem rækkerne for partitionstasterne og indekstasterne returneres.
hvor høj kardinalitetskolonne (record_link_id)indeks vil påvirke forespørgselsydelsen for ovenstående forespørgsel?
høj kardinalitetsindekser skaber i det væsentlige en række for (næsten) hver post i hovedtabellen. Ydeevne påvirkes, fordi Cassandra er designet til at udføre sekventielle læsninger for forespørgselsresultater. En indeksforespørgsel tvinger i det væsentlige Cassandra til at udføre tilfældige læsninger. Når kardinaliteten af din indekserede værdi stiger, øges den tid, det tager at finde den forespurgte værdi.
berører cassandra alle noder for ovenstående forespørgsel? Hvorfor?
Nej. Det skal kun berøre en node, der er ansvarlig for scopeid=35
og formid=78005
partitionen. Indekser gemmes ligeledes lokalt, indeholder kun poster, der er gyldige for den lokale node.
oprettelse af indeks over kolonner med høj kardinalitet vil være den hurtigste og bedste datamodel
problemet her er, at tilgangen ikke skaleres, og vil være langsom, hvisupdate_audit
er et stort datasæt. MVP Richard lav har en stor artikel om sekundære indekser (det søde sted for Cassandra sekundær indeksering), og især på dette punkt:
Hvis din tabel var betydeligt større end hukommelsen, ville en forespørgsel være meget langsom, selv for at returnere kun et par tusinde resultater. At returnere potentielt millioner af brugere ville være katastrofalt, selvom det ser ud til at være en effektiv forespørgsel.
i praksis betyder det, at indeksering er mest nyttig til at returnere tiere, måske hundredvis af resultater. Husk dette, når du næste gang overvejer at bruge et sekundært indeks.
nu vil din tilgang til først at begrænse med en bestemt partition hjælpe (da din partition helt sikkert skal passe ind i hukommelsen). Men jeg føler, at det bedre valg her ville være at gøre record_link_id
en klyngetast, i stedet for at stole på et sekundært indeks.
Rediger
hvordan har indeks på lavt kardinalitetsindeks, når der er millioner af brugere, selv når vi leverer den primære nøgle
det afhænger af, hvor brede dine rækker er. Det vanskelige ved ekstremt lave kardinalitetsindekser er, at % af de returnerede rækker normalt er større. Overvej for eksempel en bred række users
tabel. Du begrænser med partitionstasten i din forespørgsel, men der er stadig 10.000 rækker tilbage. Hvis dit indeks er på noget som gender
, skal din forespørgsel filtrere omkring halvdelen af disse rækker, som ikke fungerer godt.
sekundære indekser har tendens til at fungere bedst på (i mangel af en bedre beskrivelse) “midt på vejen” kardinalitet. Ved hjælp af ovenstående eksempel på en bred række users
tabel, et indeks på country
eller state
skal udføre meget bedre end et indeks på gender
(forudsat at de fleste af disse brugere ikke alle bor i det område, hvor de samme land eller stat).
Rediger 20180913
for dit svar på 1. spørgsmål “hvordan ovenstående forespørgsel vil fungere internt i cassandra?”, ved du, hvad der er adfærden, når du spørger med pagination?
overvej følgende diagram, taget fra Java-Driverdokumentationen (v3.6):
grundlæggende vil Personsøgning få forespørgslen til at bryde sig op og vende tilbage til klyngen for den næste iteration af resultater. Det ville være mindre sandsynligt, at timeout, men ydeevnen vil tendens nedad, proportional med størrelsen af det samlede resultat sæt og antallet af noder i klyngen.
TL;DR; jo mere efterspurgte resultater spredes over flere noder, jo længere tid tager det.