1.1 Mi az a sharding?

Ha kitartóan keresgélsz, kiderül, hogy eléggé elmosódott a határ az úgynevezett particionálás és az úgynevezett sharding között. Mindenki azt hív, amit akar, amit akar. Vannak, akik különbséget tesznek a vízszintes particionálás és a felosztás között. Mások azt mondják, hogy a felosztás egyfajta vízszintes particionálás.

Nem találtam egyetlen terminológiai szabványt sem, amelyet az alapító atyák jóváhagytak volna és az ISO tanúsított volna. A személyes belső meggyőződés valami ilyesmi: a felosztás átlagosan az alap „darabokra vágása” önkényes módon.

  • Függőleges particionálás - oszloponként. Például van egy óriási tábla pár milliárd rekorddal 60 oszlopban. Ahelyett, hogy egy ilyen óriástáblát tartanánk, 60, egyenként 2 milliárd rekordot tartalmazó, legalább óriási táblát tartunk – és ez nem oszlopalap, hanem vertikális particionálás (mint például terminológia).
  • Vízszintes particionálás - soronként vágjuk, esetleg a szerveren belül.

A kínos pillanat itt a vízszintes particionálás és a szilánkolás közötti finom különbség. Darabokra lehet vágni, de nem tudom biztosan megmondani, hogy mi az. Van egy olyan érzés, hogy a szilánkolás és a vízszintes particionálás ugyanarról szól.

A felosztás általában az, amikor egy adatbázis szempontjából nagy táblát, vagy dokumentumok pro-gyűjteményét, objektumokat, ha nincs adatbázisunk, hanem dokumentumtárolónk, pontosan az objektumok vágják szét. Vagyis 2 milliárd objektumból, mérettől függetlenül darabokat választanak ki. Magukat az objektumokat az egyes tárgyakon belül nem daraboljuk darabokra, nem rakjuk szét külön oszlopokba, vagyis kötegenként, különböző helyeken rakjuk ki őket.

Vannak finom terminológiai különbségek. Például viszonylagosan szólva a Postgres fejlesztői azt mondhatják, hogy a vízszintes particionálás az, amikor az összes tábla, amelyre a főtábla fel van osztva, ugyanabban a sémában fekszik, és ha különböző gépeken, akkor ez már sharding.

Általános értelemben, anélkül, hogy egy adott adatbázis és egy konkrét adatkezelő rendszer terminológiájához kötnénk, az az érzésünk, hogy a sharding csak sorról sorra / dokumentumról dokumentumra szeletelés, és így tovább – ennyi.

Hangsúlyozom tipikus. Abban az értelemben, hogy mindezt nem csak azért tesszük, hogy 2 milliárd dokumentumot 20 táblába vágjunk, amelyek mindegyike jobban kezelhető lenne, hanem azért, hogy sok magon, sok lemezen vagy sok különböző fizikai vagy virtuális szerveren eloszthassuk.

1.2 Oszd fel az oszthatatlant

Magától értetődik, hogy ezt úgy tesszük, hogy minden egyes szilánkot – minden adatot – sokszor megismételünk. De tényleg, nem.

INSERT INTO docs00 
SELECT * FROM documents WHERE (id%16)=0 
... 
 
INSERT INTO docs15 
SELECT * FROM documents WHERE (id%16)=15 

Valójában, ha ilyen adatszeletelést végez, és egyetlen óriási SQL-táblából a MySQL-en a bátor laptopján, akkor 16 kis táblát generál anélkül, hogy egyetlen laptopon, egyetlen sémán, egyetlen adatbázison stb. . stb. - ez az, már van szilánkolás.

Ennek eredménye a következő:

  • A sávszélesség nő.
  • A késleltetés nem változik, vagyis ebben az esetben mindenki, úgymond, munkavállaló vagy fogyasztó megkapja a magáét. A különböző kéréseket nagyjából egy időben teljesítjük.
  • Vagy mindkettő, és egy másik, és szintén magas rendelkezésre állás (replikáció).

Miért a sávszélesség? Előfordulhat, hogy olyan mennyiségű adatunk van, amelyek nem férnek el - nem világos, hogy hova, de nem férnek el - 1 {kernelen | lemez | szerver | ...}. Egyszerűen nincs elég forrás, ez minden. Ahhoz, hogy ezzel a nagy adatkészlettel dolgozhasson, ki kell vágnia.

Miért a késleltetés? Egy magon egy 2 milliárd soros tábla szkennelése 20-szor lassabb, mint 20 tábla 20 magon, párhuzamosan végzett vizsgálata. Az adatok feldolgozása túl lassan történik egyetlen erőforráson.

Miért magas a rendelkezésre állás? Vagy kivágjuk az adatokat, hogy mindkettőt egyszerre tegyük, és egyidejűleg minden szilánkból több másolatot készítsünk – a replikáció biztosítja a magas rendelkezésre állást.

1.3 Egy egyszerű példa "hogyan kell kézzel csinálni"

A feltételes felosztást a test.documents teszttábla segítségével 32 dokumentumhoz lehet kivágni, és ebből a táblázatból 16 teszttáblát generál, körülbelül 2 dokumentumot test.docs00, 01, 02, ..., 15.

INSERT INTO docs00 
SELECT * FROM documents WHERE (id%16)=0 
... 
 
INSERT INTO docs15 
SELECT * FROM documents WHERE (id%16)=15 

Miért kb? Mert eleve nem tudjuk, hogyan oszlik el az id, ha 1-től 32-ig bezárólag, akkor pontosan 2 dokumentum lesz mindegyik, különben nem.

Itt csináljuk, miért. Miután elkészítettük a 16 asztalt, 16-ot "megragadhatunk" abból, amire szükségünk van. Függetlenül attól, hogy mit találunk, ezeket az erőforrásokat párhuzamba állíthatjuk. Például, ha nincs elég lemezterület, érdemes ezeket a táblákat külön lemezekre bontani.

Mindez sajnos nem ingyenes. Gyanítom, hogy a kanonikus SQL-szabvány esetében (az SQL-szabványt régóta nem olvastam újra, lehet, hogy régen nem frissítették) nincs hivatalos szabványos szintaxis, hogy bármelyik SQL szerverre kimondjam. : "Kedves SQL szerver, készíts nekem 32 szilánkot és oszd fel 4 lemezre. De az egyes megvalósításokban gyakran létezik egy sajátos szintaxis, amely alapvetően ugyanazt a dolgot teszi. A PostgreSQL-nek vannak particionálási mechanizmusai, a MySQL-nek MariaDB-je van, az Oracle valószínűleg már régen csinálta mindezt.

Ennek ellenére, ha kézzel, adatbázis-támogatás nélkül és a szabvány keretein belül csináljuk, akkor az adatelérés bonyolultságával feltételesen fizetünk . Ahol egyszerű SELECT * FROM dokumentumok WHERE id=123 volt, most 16 x SELECT * FROM docsXX. És jó, ha megpróbáltuk kulcsonként megszerezni a lemezt. Sokkal érdekesebb lenne, ha korai lemezválasztékot próbálnánk megszerezni. Most (ha hangsúlyozom, hogy bolondok vagyunk, és a szabvány keretein belül maradunk), ennek a 16 SELECT * FROM eredményét kell kombinálni az alkalmazásban.

Milyen teljesítménybeli változásra számíthat?

  • Intuitíven - lineárisan.
  • Elméletileg - szublineáris, mert Amdahl törvény.
  • Gyakorlatilag, talán majdnem lineárisan, talán nem.

Valójában a helyes válasz ismeretlen. A sharding technika okos alkalmazásával jelentős szuperlineáris leromlást érhet el az alkalmazás teljesítményében, és még a DBA is beindul a forró pókerrel.

Lássuk, hogyan lehet ezt elérni. Nyilvánvaló, hogy nem érdekes, ha a beállítást PostgreSQL shards=16-ra állítjuk, majd az magától elindul. Gondoljuk végig, hogyan biztosíthatjuk, hogy 16-szor 32-vel lelassuljunk a szilánkolástól – ez abból a szempontból érdekes, hogy hogyan ne tegyük ezt.

A gyorsításra vagy lassításra tett kísérleteink mindig befutnak a klasszikusokba – a jó öreg Amdahl-törvénybe, amely szerint nincs tökéletes párhuzamozás egyetlen kérésnek sem, mindig van valami következetes része.

1.4 Amdahl törvény

Mindig van egy soros rész.

A lekérdezés végrehajtásának mindig van egy része, amely párhuzamos, és mindig van egy része, amely nincs párhuzamosítva. Még ha úgy tűnik is, hogy egy tökéletesen párhuzamos lekérdezés, legalább annak az eredménysornak a gyűjteménye, amelyet az egyes szilánkokból kapott sorokból el fog küldeni az ügyfélnek, mindig ott van, és mindig szekvenciális.

Mindig van valami következetes rész. Lehet apró, az általános háttér előtt teljesen láthatatlan, lehet gigantikus és ennek megfelelően erősen befolyásolja a párhuzamosítást, de mindig létezik.

Ráadásul a befolyása is változik és jelentősen nőhet, ha például a táblázatunkat - emeljük a tétet - levágjuk 64 rekordról 16, 4 rekordot tartalmazó táblázatra, ez a rész megváltozik. Természetesen ilyen gigantikus adatmennyiségből ítélve egy mobiltelefonon és egy 2 MHz-es 86-os processzoron dolgozunk, és nincs elég egyszerre nyitva tartható fájlunk. Úgy tűnik, ilyen bemenetekkel egyszerre egy fájlt nyitunk meg.

  • Összesen = Soros + Párhuzamos volt . Ahol például párhuzamos az összes munka a DB-n belül, és a soros küldi az eredményt a kliensnek.
  • Összesen2 lett = Soros + Párhuzamos/N + Xsoros . Például, ha az általános ORDER BY, Xserial>0.

Ezzel az egyszerű példával azt próbálom bemutatni, hogy megjelenik néhány Xserial. Amellett, hogy mindig van szerializált rész, és hogy párhuzamosan próbálunk adatokkal dolgozni, van egy további rész is, amely ezt az adatszeletelést biztosítja. Nagyjából a következőkre lehet szükségünk:

  • keresse meg ezt a 16 táblát az adatbázis belső szótárában;
  • fájlok megnyitása;
  • memória lefoglalása;
  • memória kiosztásának megszüntetése;
  • eredmények összevonása;
  • szinkronizálni a magok között.

Néhány szinkronon kívüli effektus továbbra is megjelenik. Lehetnek jelentéktelenek, és a teljes idő egymilliárd részét foglalják el, de mindig nem nullák, és mindig ott vannak. Segítségükkel drámaian elveszíthetjük teljesítményünket a szilánkolás után.

Ez egy standard kép az Amdahl-törvényről. Itt az a fontos, hogy a vonalak, amelyek ideális esetben egyenesek és lineárisan nőnek, aszimptotákba futnak. De mivel az internetről származó grafikon olvashatatlan, véleményem szerint vizuálisabb táblázatokat készítettem számokkal.

Tegyük fel, hogy a kérésfeldolgozásnak van néhány soros része, amely csak 5%-ot vesz igénybe: soros = 0,05 = 1/20 .

Intuitív módon úgy tűnhet, hogy egy soros résznél, amely a kérésfeldolgozásnak csak 1/20-át veszi igénybe, ha 20 magra párhuzamosítjuk a kérésfeldolgozást, körülbelül 20-szor, legrosszabb esetben 18-szor gyorsabb lesz.

Valójában a matematika szívtelen dolog :

fal = 0,05 + 0,95/magok száma, gyorsulás = 1 / (0,05 + 0,95/magok száma)

Kiderül, hogy ha gondosan kiszámolod, 5%-os szerializált résszel a gyorsulás 10-szeres lesz (10,3), ami 51% az elméleti ideálishoz képest.

8 mag = 5,9 = 74%
10 mag = 6,9 = 69%
20 mag = 10,3 = 51%
40 mag = 13,6 = 34%
128 mag = 17,4 = 14%

Ha 20 magot (ha úgy tetszik, 20 lemezt) használtunk fel arra a feladatra, amelyen az ember dolgozott, akkor még elméletileg sem fogunk húszszorosnál nagyobb gyorsulást elérni, de a gyakorlatban sokkal kevesebbet. Sőt, a párhuzamosságok számának növekedésével az eredménytelenség nagymértékben nő.

Ha a soros munka csak 1%-a marad meg, és 99%-a párhuzamos, a gyorsítási értékek valamelyest javulnak:

8 mag = 7,5 = 93%
16 mag = 13,9 = 87%
32 mag = 24,4 = 76%
64 mag = 39,3 = 61%

Egy tökéletesen termonukleáris lekérdezésnél, amelynek teljesítése természetesen órákig tart, az előkészítő munka és az eredmény összeállítása pedig nagyon kevés időt vesz igénybe (soros = 0,001), már jó hatásfokot fogunk látni:

8 mag = 7,94 = 99%
16 mag = 15,76 = 99%
32 mag = 31.04 = 97%
64 mag = 60,20 = 94%

Kérjük, vegye figyelembe, hogy soha nem fogjuk látni a 100%-ot . Kifejezetten jó esetekben látható például 99,999%, de nem pontosan 100%.