Cassandra Indexing: the Good, the Bad and The Ugly

a NoSQL-en belül az indexelés, az információ lekérése és keresése szorosan kapcsolódik a fizikai tároló mechanizmusokhoz. Fontos megjegyezni, hogy a sorok a gazdagépek között vannak tárolva, de egyetlen sor egyetlen gazdagépen van tárolva. (másolatokkal) az Oszlopcsaládok rendezett sorrendben vannak tárolva, ami hatékonyvá teszi az oszlopok lekérdezését (feltéve, hogy sorokat ölel fel).

A Rossz : Particionálás

az egyik nehéz dolog, amit először meg kell szokni, hogy indexek nélkül a sorokat átfogó lekérdezések (nagyon) rosszak lehetnek. Visszagondolva a tárolási modellünkre, ez azonban nem meglepő. Azt a stratégiát, amelyet a Cassandra használ a sorok elosztására a gazdagépek között, Particionálásnak nevezzük.

a Particionálás a sorkulcsok tartományának faragása, amely a “token ring” – be rendeli őket, amely a RowKey tartomány egy szegmenséért (azaz partíciójáért) is felelősséget ruház az egyes gazdagépekre. Valószínűleg látta ezt, amikor inicializálta a fürtöt egy “tokennel”. A token helyet ad a gazdagépnek a token gyűrű mentén, amely felelősséget ruház a token tartomány egy szakaszáért. A Particionálás a rowkey leképezése a token tartományba.

két elsődleges particionáló van: Random és Order Preserving. Megfelelően nevezik őket. A RandomPartitioner hash a rowkeys be tokenek. A RandomPartitioner, a token egy hash a rowkey. Ez jó munkát végez az adatok egyenletes elosztásában a csomópontok között, de hihetetlenül megnehezíti a rowkey tér tartományának lekérdezését. Csak a “start rowkey” és a “end rowkey” értékből a Cassandra nem tudja meghatározni, hogy a tokenterület melyik tartományára van szüksége. A lekérdezés megválaszolásához lényegében egy “táblázatos vizsgálatot” kell végrehajtania, a Cassandra-ban pedig a “táblázatos vizsgálat” rossz, mert minden gépre (valószínűleg minden gépre, ha jó hash funkcióval rendelkezik) kell mennie a lekérdezés megválaszolásához.

most, az egyenletes adatelosztás nagy költségén, alkalmazhatja az Orderpreservingpartitionert (OPP). Én *nem* Le OPP. Az OPP megőrzi a sorrendet, mivel a rowkeys-t tokenekké alakítja. Most, mivel a start rowkey értéket és a end rowkey értéket adja meg, a Cassandra * pontosan meghatározhatja, hogy mely gazdagépek rendelkeznek a keresett adatokkal. Kiszámítja a kezdő értéket egy tokennek, a végértéket pedig egy tokennek, és egyszerűen kiválaszt és visszaad mindent a kettő között. De a rend megőrzésével, kivéve, ha a rowkeys egyenletesen oszlik el a térben, a tokenek sem lesznek, és egy ferde fürtöt kapsz, ami jelentősen megnöveli a fürt konfigurálásának és adminisztrációjának költségeit. (nem éri meg)

a jó: másodlagos indexek

a Cassandra natív indexelési mechanizmust biztosít a másodlagos indexekben. A másodlagos indexek az oszlopok értékein dolgoznak. Egy oszlopcsalád másodlagos indexét deklarálja. Datastax jó dokumentációt a használat. A motorháztető alatt Cassandra indexként egy “rejtett oszlopcsaládot” tart fenn. (A részleteket lásd Ed Anuff bemutatójában) mivel a Cassandra egyetlen csomópontban sem őrzi meg az oszlopérték-információkat, és a másodlagos indexek az oszlopok értékén vannak (nem pedig a sorkulcsokon), a lekérdezést továbbra is el kell küldeni az összes csomópontnak. Ezenkívül a másodlagos indexek nem ajánlottak a magas kardinalitású készletekhez. Még nem néztem meg, de feltételezem, hogy ez a “rejtett oszlopcsaládban”használt adatmodell miatt van. Ha a rejtett oszlopcsalád egyedi értékenként egy sort tárol (oszlopként sorkulcsokkal), akkor a sorok beolvasásával meg kell határozni, hogy a lekérdezés tartományán belül vannak-e.
Ed előadásából:

  • nem ajánlott magas kardinalitási értékekhez (pl. időbélyegek,születési dátumok,kulcsszavak stb.)
  • legalább egy egyenlőségi összehasonlítást igényel egy lekérdezésben-nem nagyszerű a kevesebb, mint/nagyobb, mint a / tartomány lekérdezések
  • rendezetlen-az eredmények token sorrendben vannak, nem lekérdezési érték sorrend
  • csak adattípusokon történő keresésre korlátozódik, Cassandra natív módon megérti, hogy a lekérdezés

mindezek mellett a másodlagos indexek a dobozból működnek,és jó sikereket értünk el egyszerű értékeken.

a csúnya: csináld magad (DIY) / széles sorok

a szépség a szemlélő szemében van. A NoSQL egyik legszebb tulajdonsága az egyszerűség. A konstrukciók egyszerűek: Kulcsterek, Oszlopcsaládok, sorok és oszlopok. Tartása egyszerű azonban azt jelenti, néha meg kell venni a dolgokat a saját kezébe.

ez a helyzet a széles soros indexekkel. Kihasználva Cassandra tárolási modell, a könnyű építeni a saját indexek, ahol minden sor-kulcs válik egy oszlopot az index. Ez néha nehéz, hogy a fejed körül, de lehetővé teszi elképzelni, hogy van egy eset, amikor azt akarjuk, hogy válassza ki az összes felhasználó egy Irányítószám. A fő felhasználók oszlopcsalád be van írva a userid-re, az irányítószám minden felhasználói sorban oszlop. Használhatnánk másodlagos indexeket, de jó néhány irányítószám van. Ehelyett fenntarthatunk egy oszlopcsaládot egyetlen sorral, az úgynevezett “idx_zipcode”. Ezután oszlopokat írhatunk a “zipcode_userid”űrlap ebbe a sorába. Mivel az oszlopok rendezett sorrendben vannak tárolva, gyorsan lekérdezhető minden olyan oszlop, amely “18964” – vel kezdődik (pl. használhatjuk az 18964_ és az 18964_zzzzzz kezdő-és végértékként).

ennek a megközelítésnek az egyik nyilvánvaló hátránya, hogy a sorok önállóak a gazdagépen. (ismét a replikák kivételével) ez azt jelenti, hogy minden lekérdezés egyetlen csomópontot fog elérni. Erre még nem találtam jó választ.

ezenkívül az IMHO, a DIY wide-row indexelés legrondább része az ügyfél szempontjából. Megvalósításunk során mindent megtettünk, hogy nyelvi agnosztikusak legyünk az ügyféloldalon, lehetővé téve az emberek számára, hogy kiválasszák a legjobb eszközt a munkához, hogy kölcsönhatásba lépjenek a Cassandra adataival. Ezzel a mentalitással a barkácsolási indexek némi problémát jelentenek. A széles sorok gyakran összetett kulcsokat használnak (képzelje el, ha lenne idx_state_zip, amely lehetővé tenné az állapot szerinti lekérdezést, majd a zip-et). Bár létezik” natív ” támogatás az összetett kulcsokhoz, az összes kliens könyvtár saját verzióját valósítja meg (Hector, Astyanax és Thrift). Ez azt jelenti, hogy az adatokat lekérdező kliensnek hozzáadott logikával kell rendelkeznie az index első lekérdezéséhez, emellett minden ügyfélnek ugyanúgy kell felépítenie az összetett kulcsot.

Hogy Jobb Legyen…

éppen ezért úgy döntöttünk, hogy kiadunk két nyílt forráskódú projektet, amelyek elősegítik ezt a logikát a szerver oldalra. Az első projekt a Cassandra-Triggers. Ez lehetővé teszi, hogy aszinkron tevékenységeket csatoljon a Cassandra írásához. (az egyik ilyen tevékenység lehet az indexelés) kiadtuk a Cassandra-indexelést is. Ez még gyerekcipőben jár (például csak az UT8Types-t támogatja az indexben), de a szándék egy általános szerveroldali mechanizmus biztosítása, amely az adatokat a Cassandra-nak írt módon indexeli. Ugyanazt a szerveroldali technikát alkalmazva, mint a Cassandra-Indexelésnél, egyszerűen konfigurálja az indexelni kívánt oszlopokat, az AOP kód pedig a többit elvégzi, amikor a célnak írsz CF. Mint mindig, kérdéseket, megjegyzéseket és gondolatokat is szívesen fogadunk. (különösen, ha valahol nem vagyok bázison)

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.