StorageReview.com

Inbäddad nyckel-värde butiksprestandabenchmark

Key-value data stores (KVS) är ett snabbt växande segment av NoSQL-databasvärlden som har blivit allt populärare på sistone. Eftersom de har den enklaste datamodellen – godtycklig

bytesträngar för nycklar, parade med en bytesträng för motsvarande värde, kan de snabbt införlivas i applikationer som har mycket förenklade lagringsbehov. Deras API:er tenderar att vara lika enkla, tillhandahåller endast mycket primitiva operationer och levererar dem med mycket lite omkostnader.

Även om det finns ett antal klientserverorienterade KVS:er där ute nu, såsom memcache och redis, använder detta test bara inbäddade KVS:er – dvs KVS:er som körs helt inom applikationsprocessen, istället för att kräva kommunikation med en DB-serverprocess. Observera att KVS:er av denna typ inte är något nytt, de är bland den äldsta familjen av lagringsprogram som finns. BerkeleyDB härstammar till exempel från ett lagringsbibliotek som har använts i Unix sedan 1980-talet. Inte heller är dessa KVS:er begränsade till lokal (icke-nätverksbaserad) användning – BerkeleyDB, LMDB och TokuDB är helt transaktionella och har använts som de underliggande lagringsmotorerna för servrar som MySQL och OpenLDAP i många år. Faktum är att i alla andra datalager på högre nivå, SQL, NoSQL eller på annat sätt, hittar du en inbäddad KVS som gör själva arbetet.

Det finns massor av högprofilerade applikationer som använder KVS nu; t.ex. använder kryptovalutor som BitCoin en KVS för att lagra sin blockchain, vilket är en komplett logg över alla deras transaktioner. Projektkrav som leder till användning av en KVS kan innefatta mycket höga transaktionshastigheter (som för en stor e-handelswebbplats), mycket låg latens (t.ex. högfrekventa handlare), mycket litet fotavtryck (t.ex. mobiltelefoner och andra begränsade miljöer) eller kombinationer av alla tre.

Testerna som körs här är hämtade från benchmarkkod som ursprungligen skrevs på Google av LevelDB-författarna, och som sedan porterats till flera andra databaser av Symas Corp [ 2 ] . Testscenariot är baserat på benchmarks som utförs av Facebooks RocksDB-team [ 3 ] och en utökad version av dessa tester som täcker fler databaser och användningsfall som utförs av Symas Corp.

Det finns två faser i ett test: en bulkladdningsfas där posterna laddas i sekventiell ordning, och sedan en läs-skrivfas som får tillgång till posterna i slumpmässig ordning.

Alla DB-motorer som testas här är inbäddade nyckel-/värdelagringar som lagrar nycklar i sorterad ordning, vilket stöder ordnad korsning av nycklar. Som sådana använder de alla varianter av en sökträdsdatastruktur. Testdatauppsättningen är vald att vara ungefär 5 gånger större än RAM på testservrarna, för att visa utrymme och I/O-effektivitet för varje DB-motor.

Även om de underliggande koncepten är relaterade, tar DB-motorerna alla vitt skilda tillvägagångssätt för sina implementeringar. De flesta av dem försöker hantera sina egna datacchar, i ett försök att minimera antalet fysiska I/O-operationer som behövs för en given arbetsbelastning. Varje tillvägagångssätt innebär en avvägning mellan utrymme och tid: att använda en viss mängd utrymme kan spara en viss mängd tid under en given omständighet, men att besparingar oundvikligen kommer att betalas tillbaka i någon annan aspekt:

RocksDB byter ut enkelhet mot prestanda – det kräver den mest komplexa inställningen, med över 40 parametrar som måste ställas in optimalt för att leverera bästa prestanda. TokuDB och BerkeleyDB följer när det gäller konfigurationskomplexitet. LevelDB och LMDB strävar efter enkel konfiguration, med LMDB som inte kräver någon justering alls.

RocksDB, LevelDB och TokuDB fokuserar på skrivprestanda; deras Log Structured Merge (LSM) Tree och Fractal Tree (FT) design, förlitar sig starkt på användarkonfigurerade skrivbuffertar för att aggregera skrivningar i minnet innan de överför dem till disk, vilket gör att de slutliga skrivningarna kan skrivas sekventiellt och därmed som högsta hastigheten på det underliggande mediet. Avvägningen är att den idealiska ordningen för skrivningar inte är idealisk för läsningar, och deras läsprestanda är betydligt sämre. BerkeleyDB och LMDB är mer traditionella B+tree-designer, som fokuserar mer på läsprestanda än skrivprestanda.

WiredTiger försöker täcka alla baser och erbjuder både LSM- och B+tree-motorer i deras bibliotek. Denna flexibilitet kräver också en måttlig nivå av konfigurationskomplexitet.

RocksDB- och LevelDB-remsfunktioner samtidigt som de strävar efter maximal skrivprestanda. BerkeleyDB, LMDB, TokuDB och WiredTiger fokuserar på tillförlitlighet och erbjuder fullständiga ACID-transaktioner. Som sådan är de fyra sistnämnda motorerna lätt anpassade för användning i SQL-servrar, LDAP-servrar och andra transaktionsorienterade applikationer medan de två förstnämnda är mindre lämpliga för sådan användning.

Alla motorer utom LMDB använder sina egna explicit hanterade skrivbuffertar och datacache. LMDB använder endast operativsystemets sidcache. Som sådan har alla motorer förutom LMDB betydande CPU-overhead på grund av att de hanterar dessa buffertar och kopierar data flera gånger mellan dessa buffertar. Till exempel, när man hämtar en post från disk som inte tidigare cachades, utför BerkeleyDB minst en kopia från minne till minne – först läses data av operativsystemet in i dess sidcache, sedan kopieras den till BerkeleyDB:s sidcache. Slutligen kopieras data från BerkeleyDB-cachen till den av användaren tillhandahållna bufferten. LMDB är nollkopia; data går direkt från lagringsenheten till OS-sidans cache, och dessa data lämnas tillbaka direkt till användaren. Motorer som TokuDB utför ännu fler kopior, eftersom data på disken genomgår flera formatomvandlingar innan de returneras till användaren. Dessa flera steg förbrukar vart och ett minne, så minneskopieringsarkitekturen har direkt betydelse för hur många poster som får plats i RAM samtidigt, och därmed hur stor en arbetsuppsättning som kan köras i full hastighet. Eftersom LMDB inte gör några egna kopior kan den hantera den största datamängden för en given storlek på RAM.

Vissa av DB-motorerna är designade för att vara mer optimala för skrivoperationer, och vissa är optimerade mer för läsningar. Bulkbelastningsfasen visar deras bästa skrivhastighet. Den slumpmässiga läs-skrivfasen visar deras värsta skrivhastighet, där en enskild tråd utför skrivningar till slumpmässigt valda poster, medan XX trådar utför samtidiga läsningar till andra slumpmässigt valda poster. Den visar också hur varje motor hanterar avläsningar i en hårt belastad miljö.

Som Symas-testerna visade är den relativa prestandan för varje DB-motor starkt beroende av storleken på de poster som används. Rekordstorleken som väljs här är en grov kompromiss mellan de större rekorden (där traditionella Btree-baserade motorer utmärker sig) och de mindre rekorden (där de LSM-baserade designerna utmärker sig).