Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Di payîza sala 2019-an de, di tîmê Mail.ru Cloud iOS de bûyerek dirêj-hêvî bû. Databasa sereke ji bo hilanîna domdar a dewleta serîlêdanê ji bo cîhana mobîl pir xerîb bûye Birûsk Memory-Mapped Database (LMDB). Li jêr qutkirinê em ji çar beşan vekolînek berfireh a wê pêşkêşî we dikin. Pêşî, bila em li ser sedemên hilbijarkek wusa ne-pîvan û dijwar bipeyivin. Dûv re em ê herin ku sê stûnên di dilê mîmariya LMDB de bihesibînin: pelên bi nexşeya bîranîn, B+-dara, nêzîkatiya kopî-li-nivîsandinê ji bo pêkanîna danûstendinê û pirguhertoyê. Di dawiyê de, ji bo şîrîn - beşa pratîkî. Di wê de em ê binihêrin ka meriv çawa li ser API-ya-nirxa nizm-asta nizm bi çend tabloyan, di nav de nîşanek, sêwiranek databasê çawa sêwirand û bicîh tîne.

Contains

  1. Motivasyona ji bo pêkanîna
  2. LMDB Positioning
  3. Sê stûnên LMDB
    3.1. Whale #1. Pelên bîranîn-nexşe
    3.2. Whale #2. B+ dar
    3.3. Whale #3. Kopî-li-nivîsandin
  4. Sêwirana şemaya daneyê li ser API-ya key-nirxê
    4.1. Abstractions bingehîn
    4.2. Table Modeling
    4.3. Modelkirina têkiliyên di navbera tabloyan de

1. Motîvasyona ji bo pêkanîna

Salek di 2015-an de, me zehmetî kişand ku em bipîvin ka çend caran pêwendiya serîlêdana me dereng dimîne. Me ev yek ji ber sedemek kir. Me gilî û gazincên pir caran werdigirin ku carinan serîlêdan bersivê dide kiryarên bikarhêner: bişkok nayên pê kirin, navnîşan nagerin, hwd. Li ser mekanîka pîvandinê got li ser AvitoTech, ji ber vê yekê ez li vir tenê rêza hejmaran didim.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Encamên pîvandinê ji bo me bû serşokek sar. Derket holê ku ji yên din gelek zêdetir pirsgirêkên ku ji ber cemidandinê çêdibin hene. Ger beriya ku vê rastiyê fêm bikin nîşana teknîkî ya sereke ya kalîteyê bê şikestin bû, wê hingê piştî balê veguherandin li ser freeze free.

Ava kirin dashboard bi cemidandin û piştî xerckirinê hejmarî и çêwe analîzkirina sedemên wan, dijminê sereke zelal bû - mantiqa karsaziya giran ku di mijara sereke ya serîlêdanê de hatî darve kirin. Reaksiyona xwezayî ya li hember vê riswatiyê xwestekek şewitî bû ku wê biavêje nav çemên xebatê. Ji bo ku em vê pirsgirêkê bi rêkûpêk çareser bikin, me serî li mîmariyek pir-tevlihev a li ser aktorên sivik girt. Min ew ji bo adaptasyona wê ya ji bo cîhana iOS veqetand du têlan li ser Twitter kolektîf û gotara li ser Habré. Wekî beşek ji vegotina heyî, ez dixwazim balê bikişînim ser wan aliyên biryarê yên ku bandor li bijartina databasê kir.

Modela lîstikvan a rêxistina pergalê texmîn dike ku pirtextî dibe cewhera wê ya duyemîn. Tiştên modelê yên tê de hez dikin ku sînorên çeman derbas bikin. Û ew vê yekê ne carinan û vir û wir, lê hema hema bi berdewamî û li her derê dikin.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Database yek ji hêmanên bingehîn ên di diagrama pêşkêşkirî de ye. Karê wê yê sereke pêkanîna makropatternê ye Database Shared. Ger di cîhana pargîdaniyê de ew ji bo organîzekirina hevdemkirina daneyê di navbera karûbaran de tê bikar anîn, wê hingê di mijara mîmariya lîstikvan de - daneyên di navbera mijaran de. Bi vî rengî, ji me re databasek hewce bû ku dema ku bi wê re di hawîrdorek pir-mijarî de bixebite nebe sedema zehmetiyên hindiktirîn jî. Bi taybetî, ev tê vê wateyê ku tiştên ku ji wê têne wergirtin divê bi kêmî ve ewledar bin, û bi îdeal bi tevahî neguhêrbar bin. Wekî ku hûn dizanin, ya paşîn dikare bi hevdemî ji çend mijaran were bikar anîn bêyî ku serî li ti kilîtkirinê bide, ku bandorek bikêr li ser performansê dike.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDBFaktora duyemîn a girîng ku bandor li bijartina databasê kir API-ya meya cloudê bû. Ew ji nêzîkatiya hevdemkirinê ya ku ji hêla git ve hatî pejirandin ve hatî îlhama kirin. Weke wî me jî armanc kir offline-yekemîn API, ku ji bo xerîdarên ewr guncantir xuya dike. Tê texmîn kirin ku ew ê tenê carekê rewşa tevahî ya ewr derxînin, û dûv re di pirraniya bûyeran de hevdengkirin dê bi guheztina guhertinan pêk were. Mixabin, ev derfet hîna jî tenê di qada teorîkî de ye, û xerîdar fêr nebûne ka meriv çawa di pratîkê de bi paçan re bixebite. Ji bo vê yekê çend sedemên objektîf hene, ji bo ku pêşgotinê dereng nemînin, em ê li dû xwe bihêlin. Naha, ya ku pir zêde balkêş e, encamên hînker ên dersê ye ku çi diqewime dema ku API dibêje "A" û xerîdarek wê nabêje "B".

Ji ber vê yekê, heke hûn git-ê xeyal bikin, ku dema ku fermanek kişandinê pêk tîne, li şûna ku pêçan li wêneyek herêmî bicîh bîne, rewşa xwe ya tevahî bi rewşa serverê ya tevahî re bide ber hev, wê hingê hûn ê xwediyê ramanek pir rast bin ka çawa hevdemkirin di ewr de çêdibe. mişterîyên. Hêsan e ku meriv texmîn bike ku ji bo bicîhkirina wê, hûn hewce ne ku du darên DOM-ê di bîranînê de bi meta-agahdariya li ser hemî pelên server û herêmî veqetînin. Derket holê ku ger bikarhênerek 500 hezar pelan di ewr de hilîne, wê hingê ji bo hevdengkirina wê pêdivî ye ku du darên bi 1 mîlyon girêkan ji nû ve werin afirandin û hilweşandin. Lê her girêk kombûnek e ku grafîkek ji bine-objektan vedihewîne. Di vê ronahiyê de, encamên profîlkirinê dihat hêvîkirin. Derket holê ku tewra bêyî girtina algorîtmaya hevgirtinê jî, prosedûra afirandina û dûv re jî hilweşandina hejmareke mezin ji tiştên piçûk, ji ber vê yekê ku operasyona bingehîn a hevdemkirinê di hejmareke mezin de tê xerakirin, rewş xirabtir dibe ji nivîsarên bikarhêner. Wekî encamek, em di hilbijartina databasê de pîvana duyemîn a girîng rast dikin - şiyana pêkanîna operasyonên CRUD bêyî dabeşkirina dînamîkî ya tiştan.

Pêdiviyên din kevneşoptir in û tevahiya navnîşa wan wiha ye.

  1. Ewlehiya mijarê.
  2. Multiprocessing. Ji hêla xwestina karanîna heman mînaka databasê ve hatî rêve kirin da ku dewletê ne tenê di navbera mijaran de, lê di heman demê de di navbera serîlêdana sereke û pêvekên iOS-ê de hevdeng bike.
  3. Hêza temsîlkirina hebûnên hilanîn wekî tiştên neguhêrbar.
  4. Di nav operasyonên CRUD de veqetandinên dînamîkî tune.
  5. Piştgiriya danûstendinê ji bo taybetmendiyên bingehîn TIRŞ: atomîbûn, pêkvebûn, veqetandin û pêbawerî.
  6. Li ser dozên herî populer bilezînin.

Digel vê komek hewcedariyên, SQLite hilbijartinek baş bû û dimîne. Lêbelê, di çarçoveya lêkolîna alternatîfan de, ez rastî pirtûkek hatim "Destpêkirina LevelDB". Di bin serokatiya wê de, pîvanek hate nivîsandin ku leza xebatê bi databasên cihêreng re di senaryoyên ewr ên rastîn de berhev dike. Encam hêviyên me yên herî hov derbas kir. Di rewşên herî populer de - girtina kursorek li ser navnîşek rêzkirî ya hemî pelan û navnîşek rêzkirî ya hemî pelan ji bo pelrêçek diyarkirî - LMDB derket ku 10 carî ji SQLite zûtir bû. Hilbijartin eşkere bû.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

2. LMDB Positioning

LMDB pirtûkxaneyek pir piçûk e (tenê 10K rêz) ku qata bingehîn a herî jêrîn - hilanînê bicîh tîne.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Diagrama jorîn destnîşan dike ku berhevdana LMDB bi SQLite re, ku di heman demê de astên bilindtir bicîh tîne, bi gelemperî ji SQLite bi Daneyên Core re ne rasttir e. Dê adiltir be ku meriv heman motorên hilanînê wekî hevrikên wekhev binav bike - BerkeleyDB, LevelDB, Sophia, RocksDB, hwd. Tewra pêşkeftin hene ku LMDB ji bo SQLite wekî hêmanek motora hilanînê tevdigere. Yekem ceribandina bi vî rengî di sala 2012 de bû xerc kirin ji hêla LMDB ve Howard Chu. Encam ew qas balkêş derket ku însiyatîfa wî ji hêla dildarên OSS ve hate hildan, û berdewamiya xwe di mirov de dît. LumoSQL. Di Çile 2020 de, nivîskarê vê projeyê Den Shearer bû pêşkêş kirin ew li LinuxConfAu.

LMDB bi piranî wekî motorek ji bo databasên serîlêdanê tê bikar anîn. Pirtûkxane xuyangê xwe deyndarê pêşdebiran e OpenLDAP, ku ji BerkeleyDB wekî bingeha projeya xwe pir nerazî bûn. Ji pirtûkxaneyek nerm dest pê dike btree, Howard Chu karibû ku yek ji alternatîfên herî populer ên dema me biafirîne. Wî rapora xwe ya pir xweş ji vê çîrokê re, û hem jî ji avahiya navxweyî ya LMDB re veqetand. "Bangeya Daneyên Bîra Nexşeya Birûskê". Nimûneyek baş a bidestxistina depoyek ji hêla Leonid Yuryev ve hate parve kirin (aka yleo) ji Teknolojiyên Positive di rapora xwe ya li Highload 2015 de "Motora LMDB şampiyonek taybetî ye". Di wê de, ew li ser LMDB di çarçoweya peywirek wekhev a bicihanîna ReOpenLDAP-ê de diaxive, û LevelDB berê rastî rexneyên berawirdî hatiye. Di encama pêkanînê de, Teknolojiyên Positive tewra xwedan qonaxek çalak a pêşkeftî bû MDBX bi taybetmendiyên pir xweş, xweşbîn û rastkirinên xeletiyan.

LMDB bi gelemperî wekî hilanînek wekî-ê tête bikar anîn. Mînakî, geroka Mozilla Firefox hilbijart ew ji bo hejmarek hewcedariyên, û, ji guhertoya 9, Xcode dest pê dike tercîh kirin SQLite wê ji bo hilanîna indexan.

Motora di cîhana pêşkeftina mobîl de jî mohra xwe daye. Şopên bikaranîna wê dibe bibînin di muwekîlê iOS-ê de ji bo Telegram. LinkedIn hê pêşda çû û LMDB wekî hilanînê hilbijart ji bo çarçoweya hilgirtina daneya xweya mezin Rocket Data, ku der barê wê de ye. got di gotara xwe ya 2016 de.

LMDB bi serfirazî ji bo cîhek di tavê de di nav cîhê ku ji hêla BerkeleyDB ve hatî hiştin piştî ku ket bin kontrola Oracle şer dike. Pirtûkxane ji ber lez û pêbaweriya xwe tê hezkirin, hetta li gorî hevalên xwe. Wekî ku hûn dizanin, xwarina belaş tune, û ez dixwazim balê bikişînim ser bazirganiya ku hûn ê dema ku di navbera LMDB û SQLite de hilbijêrin pê re rû bi rû bimînin. Diagrama li jor bi zelalî destnîşan dike ka çiqas leza zêde tê bidestxistin. Ya yekem, em ji bo qatên zêde yên abstractionê li ser hilanîna dîskê nadin. Eşkere ye ku mîmariyek baş hîn jî bêyî wan nikare bike, û ew ê bê guman di koda serîlêdanê de xuya bibin, lê ew ê pir nazik bin. Ew ê taybetmendiyên ku ji hêla serîlêdanek taybetî ve ne hewce ne nebin, mînakî, piştgirî ji bo pirsên bi zimanê SQL. Ya duyemîn, mimkun dibe ku bi rengek çêtirîn nexşeya karûbarên serîlêdanê li ser daxwazên hilanîna dîskê bicîh bikin. Ger SQLite di karê min de li ser bingeha hewcedariyên statîstîkî yên navînî yên serîlêdanek navînî ye, wê hingê hûn, wekî pêşdebirek serîlêdanê, ji senaryoyên xebata sereke baş dizanin. Ji bo çareseriyek hilberdartir, hûn ê hem ji bo pêşkeftina çareseriya destpêkê û hem jî ji bo piştevaniya wê ya paşîn nirxek zêde bidin.

3. Sê stûnên LMDB

Dema ku ji çavê çûk li LMDB-ê nihêrî, wextê kûr bû. Sê beşên din dê ji bo analîzkirina stûnên sereke yên ku mîmariya hilanînê li ser wan radiweste were veqetandin:

  1. Pelên nexşeya bîranînê wekî mekanîzmayek ji bo xebitandina dîskê û hevdengkirina strukturên daneya hundurîn.
  2. B+-dara wekî rêxistinek avahiya daneyên hilanîn.
  3. Kopî-li-nivîsandinê wekî nêzîkatiyek peydakirina taybetmendiyên danûstendina ACID û pirzimanî.

3.1. Whale #1. Pelên bîranîn-nexşe

Pelên bi nexşeya bîranînê hêmanek mîmarî ya wusa girîng in ku ew di nav navê depoyê de jî xuya dikin. Pirsgirêkên cachkirin û hevdemkirina gihîştina agahdariya hilanîn bi tevahî ji pergala xebitandinê re têne hiştin. LMDB di hundurê xwe de ti cache nagire. Ev ji hêla nivîskar ve biryarek hişmendî ye, ji ber ku xwendina daneyan rasterast ji pelên nexşeyê dihêle hûn di pêkanîna motorê de gelek quncikên qut bikin. Li jêr navnîşek ji hindek ji wan dûr e.

  1. Dema ku ji gelek pêvajoyan bi wê re dixebitin, parastina hevrêziya daneyan di hilanînê de dibe berpirsiyariya pergala xebitandinê. Di beşa pêş de, ev mekanîka bi hûrgulî û bi wêneyan tê nîqaş kirin.
  2. Nebûna caches bi tevahî LMDB-ê ji sermayê ku bi veqetandinên dînamîkî ve girêdayî ye ji holê radike. Di pratîkê de xwendina daneyan tê vê wateyê ku di bîranîna virtual de nîşanek li navnîşana rast destnîşan bike û ne tiştek din. Ew mîna çîroka zanistî dixuye, lê di koda çavkaniya hilanînê de hemî bangên calloc di fonksiyona veavakirina hilanînê de têne berhev kirin.
  3. Nebûna cache di heman demê de tê wateya nebûna qeflên ku bi hevdemkirina gihîştina wan re têkildar in. Xwendevanên ku di heman demê de hejmareke keyfî ya xwendevanan hebin, di rêya daneyan de bi yek mutex re rûbirû nabin. Ji ber vê yekê, leza xwendinê li ser bingeha hejmara CPU-yan xwedan pîvana xêzikî ya îdeal e. Di LMDB de, tenê operasyonên guheztinê têne hevdem kirin. Di demekê de tenê nivîskarek dikare hebe.
  4. Kêmtirîn mantiqa cachkirin û hevdengkirinê celebek pir tevlihev a xeletiyên ku bi xebata di hawîrdorek pir-tehlî ve girêdayî ne ji holê radike. Di konferansa Usenix OSDI 2014 de du lêkolînên databasên balkêş hebûn: "Hemû Pergalên Pelê Wekhevی Neی Afirandin: Li Ser Tevliheviya Çêkirina Serlêdanên Hevaheng-Crash" и "Îşkencekirina databasên ji bo kêf û qezencê". Ji wan hûn dikarin hem di derheqê pêbaweriya nedîtî ya LMDB û hem jî pêkanîna hema hema bêkêmasî ya taybetmendiyên danûstendinê yên ACID, ku ji ya SQLite-ê bilindtir e, agahdar bikin.
  5. Mînîmalîzma LMDB dihêle ku nûneriya makîneya koda wê bi tevahî di cache L1 ya pêvajoyê de bi taybetmendiyên leza peydakirî ve were cîh kirin.

Mixabin, di iOS-ê de, digel pelên nexşeya bîranînê, her tişt ew qas ku em dixwazin ne ewr e. Ji bo ku bêtir bi zanebûn li ser kêmasiyên bi wan re têkildar biaxivin, pêdivî ye ku meriv prensîbên gelemperî yên pêkanîna vê mekanîzmayê di pergalên xebitandinê de bi bîr bîne.

Agahdariya gelemperî li ser pelên bîranîn-nexşe

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDBBi her serîlêdana ku dimeşe, pergala xebitandinê saziyek ku jê re pêvajo tê gotin ve girêdayî ye. Her pêvajoyek rêzek navnîşanek domdar tê veqetandin ku tê de her tiştê ku ew hewce dike ku bixebite cîh digire. Di navnîşanên herî jêrîn de beşên bi kod û dane û çavkaniyên hişk-kodkirî hene. Dûv re blokek mezin a cîhê navnîşana dînamîkî tê, ku ji me re di bin navê heap de baş tê zanîn. Ew navnîşanên sazûmanên ku di dema xebata bernameyê de xuya dibin vedihewîne. Li jor qada bîranînê ye ku ji hêla stacka serîlêdanê ve tê bikar anîn. Bi gotineke din, mezinbûna wê jî xwedan cewherek dînamîk e; Ji bo ku stêk û hep bi hevûdu re nehêlin û destwerdanê nekin, ew li dawiya cîhê navnîşanê cihê ne. Di navbera her du beşên dînamîkî de li jor û jêrîn qulikek heye. Pergala xebitandinê di vê beşa navîn de navnîşanan bikar tîne da ku cûrbecûr saziyan bi pêvajoyê re têkildar bike. Bi taybetî, ew dikare komek domdar a navnîşanan bi pelek li ser dîskê re têkildar bike. Ji pelek weha re tê gotin ku nexşeya bîranîn.

Cihê navnîşana ku ji pêvajoyê re hatî veqetandin pir mezin e. Ji hêla teorîkî ve, hejmara navnîşan tenê ji hêla mezinahiya nîşanderê ve, ku ji hêla kapasîteya bit ya pergalê ve tête diyar kirin, sînordar e. Ger bîranîna laşî bi wê 1-bi-1 ve were nexşe kirin, wê hingê pêvajoya yekem dê tevahiya RAM-ê bişewitîne, û dê li ser ti pirtasking tune be.

Lêbelê, ji ezmûna me em dizanin ku pergalên xebitandinê yên nûjen dikarin di heman demê de bi qasî ku tê xwestin pêvajoyên xwe bicîh bînin. Ev mimkun e ji ber vê yekê ku ew tenê gelek bîranîn ji pêvajoyên li ser kaxezê re vediqetînin, lê di rastiyê de ew tenê wê beşa ku li vir û nuha tê xwestin di bîra laşî ya bingehîn de bar dikin. Ji ber vê yekê, bîranîna ku bi pêvajoyek ve girêdayî ye virtual tê gotin.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Pergala xebitandinê bîranîna virtual û laşî di nav rûpelên pîvanek diyar de birêxistin dike. Mîna ku rûpelek hin bîranîna virtual tê xwestin, pergala xebitandinê wê di bîra laşî de bar dike û wan di tabloyek taybetî de li hev dike. Ger hêlînên belaş tune ne, wê hingê yek ji rûpelên berê yên hatî barkirin li ser dîskê tê kopî kirin, û ya ku tê xwestin cihê xwe digire. Ev prosedur, ku em ê di demek nêzîk de vegerin, jê re guheztin tê gotin. Nîgara jêrîn pêvajoya ku hatî diyar kirin nîşan dide. Li ser wê, rûpela A bi navnîşana 0 hate barkirin û li ser rûpela bîranîna sereke ya bi navnîşana 4 hate danîn.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Çîrok bi pelên ku li ser bîranînê hatine nexşe kirin tam heman e. Bi mentiqî, ew bi domdarî û bi tevahî di cîhê navnîşana virtual de cih digirin. Lêbelê, ew rûpel bi rûpel û tenê li ser daxwazê ​​dikevin bîra laşî. Guhertina van rûpelan bi pelê li ser dîskê re hevdeng e. Bi vî rengî, hûn dikarin pelê I/O bi tenê bi karkirina baytên di bîranînê de pêk bînin - hemî guhertin dê bixweber ji hêla kernelê pergala xebitandinê ve li pelê çavkaniyê werin veguheztin.​
To
Wêneya jêrîn destnîşan dike ka LMDB çawa dema ku ji pêvajoyên cihêreng bi databasê re dixebite rewşa xwe hevdeng dike. Bi nexşeya bîranîna virtual ya pêvajoyên cihêreng li heman pelê, em defakto pergala xebitandinê ferz dikin ku hin blokên cîhên navnîşana wan bi hevûdu re, ku LMDB lê xuya dike, bi rengek transîtîv hevdeng bike.
To

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Nîşanek girîng ev e ku LMDB, ji hêla xwerû, pelê daneyê bi mekanîzmaya banga pergala nivîsandinê diguhezîne, û pelê bixwe di moda tenê-xwendinê de nîşan dide. Ev nêzîkatî du encamên girîng hene.

Encama yekem ji bo hemî pergalên xebitandinê hevpar e. Esasê wê ev e ku ji hêla koda çewt ve parastina li dijî zirara nezan li databasê zêde bike. Wekî ku hûn dizanin, rêwerzên bikêrhatî yên pêvajoyek belaş e ku meriv bigihîje daneyan ji her deverê di cîhê navnîşana wê de. Di heman demê de, wekî ku me tenê ji bîr kir, nîşandana pelek di moda xwendin-nivîsandinê de tê vê wateyê ku her rêwerzek jî dikare wê biguhezîne. Ger ew vê yekê bi xeletî bike, wek nimûne, hewl bide ku bi rastî hêmanek rêzê li ser navnîşek neheyî binivîsîne, wê hingê ew dikare bi xeletî pelê ku li vê navnîşanê hatî nexşe kirin biguhezîne, ku dê bibe sedema xerabûna databasê. Ger pel di moda tenê-xwendinê de were xuyang kirin, wê hingê hewildanek ji bo guhertina cîhê navnîşana têkildar dê bibe sedema bidawîbûna awarte ya bernameyê bi îşaretek SIGSEGV, û pel dê saxlem bimîne.

Encama duyemîn jixwe ji iOS re taybetî ye. Ne nivîskar û ne jî çavkaniyên din bi eşkere behsa wê nakin, lê bêyî wê LMDB dê ji bo xebitandina li ser vê pergala xebitandina mobîl ne maqûl be. Beşa paşîn ji bo nirxandina wê ve girêdayî ye.

Taybetmendiyên pelên bîranîn-nexşeya di iOS-ê de

Di sala 2018 de li WWDC raporek ecêb hebû "IOS Memory Deep Dive". Ew ji me re vedibêje ku di iOS-ê de, hemî rûpelên ku di bîra laşî de cih digirin yek ji 3 celeb in: qirêj, pêçandî û paqij.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Bîra paqij berhevokek rûpelan e ku dikare bê êş ji bîra laşî were rakirin. Daneyên ku ew tê de hene dikarin ji çavkaniyên wê yên orîjînal wekî ku hewce be ji nû ve werin barkirin. Pelên nexşeya bîranîn-tenê xwendinê dikevin vê kategoriyê. iOS natirse ku di her kêliyê de rûpelên ku bi pelê ve hatine nexşe kirin ji bîranînê dakêşin, ji ber ku ew garantî ne ku bi pelê li ser dîskê re hevdeng bibin.
To
Hemî rûpelên ku hatine guheztin di bîranîna qirêj de diqedin, ne girîng e ku ew bi eslê xwe li ku derê bûn. Bi taybetî, pelên nexşeya bîranînê yên ku bi nivîsandina bîranîna virtual ya bi wan re têkildar têne guheztin dê bi vî rengî bêne dabeş kirin. Vekirina LMDB bi ala MDB_WRITEMAP, piştî ku hûn guheztinan li wê bikin, hûn dikarin vê bi kesane verast bikin.

Gava ku serîlêdanek dest pê dike ku pir zêde bîranîna laşî bigire, iOS wê li ser pelçiqandina rûpela qirêj dike. Tevahiya bîranîna ku ji hêla rûpelên qirêj û pêçandî ve hatî dagir kirin, bi navê şopa bîranînê ya serîlêdanê pêk tîne. Gava ku ew digihîje nirxek berxek diyarkirî, daemonê pergala kujer OOM piştî pêvajoyê tê û bi zorê wê biqedîne. Ev taybetmendiya iOS-ê li gorî pergalên xebitandinê yên sermaseyê ye. Berevajî vê, kêmkirina şopa bîranînê bi guheztina rûpelan ji bîranîna laşî ber bi dîskê ve di iOS-ê de nayê peyda kirin Sedem tenê têne texmîn kirin. Dibe ku prosedûra guheztina bi tundî ya rûpelan ber bi dîskê û paş ve ji bo cîhazên desta pir enerjiyê xerc dike, an iOS çavkaniya nûnivîsandina hucreyan li ser ajokarên SSD-ê xilas dike, an jî dibe ku sêwiraner ji performansa giştî ya pergalê razî nebin, ku her tişt tê de ye. bi berdewamî veguherandin. Weha be, rastî rastiyek dimîne.

Nûçeya baş, ku berê berê hatî behs kirin, ev e ku LMDB ji hêla xwerû ve mekanîzmaya mmap-ê ji bo nûvekirina pelan bikar nayîne. Ev tê vê wateyê ku daneyên ku têne xuyang kirin ji hêla iOS ve wekî bîranîna paqij têne dabeş kirin û beşdarî şopa bîranînê nabe. Hûn dikarin vê yekê bi karanîna amûrek Xcode ya bi navê VM Tracker verast bikin. Wêneya jêrîn di dema xebatê de rewşa bîranîna virtual iOS ya serîlêdana Cloud nîşan dide. Di destpêkê de, 2 mînakên LMDB di wê de hatin destpêkirin. Ya yekem destûr da ku pelê xwe li ser 1GiB bîranîna virtual nîşan bide, ya duyemîn - 512MiB. Tevî vê rastiyê ku her du depo jî hejmareke diyar a bîranîna niştecîh digire, yek ji wan jî mezinahiya qirêj nake.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Û niha dema nûçeyên xirab e. Bi saya mekanîzmaya guheztinê di pergalên xebitandinê yên sermaseya 64-bit de, her pêvajo dikare bi qasî ku cîhê dîska hişk a belaş ji bo veguheztina potansiyela xwe destûrê dide cîhê navnîşana virtual dagir bike. Di iOS-ê de guheztina swap-ê bi kompresyonê re herî zêde ya teorîkî kêm dike. Naha pêdivî ye ku hemî pêvajoyên zindî di nav bîranîna sereke (RAM-ê bixwînin) de bi cih bibin, û hemî yên ku neguncînin divê bêne neçar kirin ku biqedin. Ev wekî ku li jor behskirî ye nûçeû di belgeyên fermî. Wekî encamek, iOS bi giranî mîqdara bîranîna ku ji bo veqetandinê bi navgîniya mmap-ê ve peyda dibe sînordar dike. Vir vir Hûn dikarin li sînorên ampîrîkî yên mîqdara bîranînê ya ku li ser cîhazên cihêreng bi karanîna vê banga pergalê ve were veqetandin binihêrin. Di modelên herî nûjen ên smartphone de, iOS bi 2 gîgabaytan, û li ser guhertoyên top ên iPad-ê - bi 4-ê bi comerdî bûye. Di pratîkê de, bê guman, divê hûn bala xwe bidin ser modelên cîhaza piştgirî yên herî kêm, ku her tişt pir xemgîn e. Ya xirabtir jî, bi nihêrîna rewşa bîranîna serîlêdanê ya di VM Tracker de, hûn ê bibînin ku LMDB ji yekane ku îdîa dike ku nexşeya bîranînê ye dûr e. Parçeyên baş ji hêla veqetankerên pergalê, pelên çavkaniyê, çarçoveyên wêneyê, û nêçîrvanên piçûk ên din ve têne xwarin.

Li ser bingeha encamên ceribandinên li Cloud-ê, em gihîştin nirxên lihevkirinê yên jêrîn ji bo bîranîna ku ji hêla LMDB ve hatî veqetandin: 384 megabytes ji bo cîhazên 32-bit û 768 ji bo cîhazên 64-bit. Piştî ku ev hejmar tê bikar anîn, her operasiyonên guheztinê bi kodê dest pê dike MDB_MAP_FULL. Em di şopandina xwe de xeletiyên weha dibînin, lê ew qas piçûk in ku di vê qonaxê de dikarin werin paşguh kirin.

Sedemek ne diyar a vexwarina zêde ya bîranînê ji hêla hilanînê ve dibe ku danûstandinên demdirêj be. Ji bo ku em fêm bikin ka van her du fenomenan çawa bi hev ve girêdayî ne, em ê ji hêla du stûnên mayî yên LMDB-ê venihêrin bibin alîkar.

3.2. Whale #2. B+ dar

Ji bo ku tabloyên li ser depoyek-nirxa sereke bişopînin, divê operasyonên jêrîn di API-ya wê de hebin:

  1. Têxistina hêmanek nû.
  2. Li hêmanek bi mifteyek diyarkirî bigerin.
  3. Rakirina hêmanek.
  4. Li ser navberên bişkokan bi rêza ku têne rêz kirin dubare bikin.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDBStruktura daneya herî hêsan ku dikare bi hêsanî her çar operasyonan bicîh bîne dara lêgerînê ya binary e. Her girêka wê mifteyek temsîl dike ku tevaya binkoma kilîtên zarokan dike du binerd. Ya çepê yên ku ji yê dêûbav piçûktir in, û ya rastê yên ku mezintir in vedihewîne. Bidestxistina komek rêzkirî ya mifteyan bi yek ji rêwiyên dara klasîk ve tê bidestxistin.

Darên binary du xeletiyên bingehîn hene ku nahêlin ku ew wekî avahiyek daneya-based dîskê bi bandor bin. Ya yekem, asta hevsengiya wan nayê pêşbînîkirin. Metirsiyek girîng a bidestxistina daran heye ku tê de bilindahiya şaxên cihêreng dikarin pir cûda bibin, ku ev yek li gorî ya ku tê hêvî kirin tevliheviya algorîtmîkî ya lêgerînê bi girîng xirabtir dike. Ya duyemîn jî, pirbûna girêdanên xaçê di navbera girêkan de darên binary di bîranînê de ji cihêbûnê bêpar dihêle. Wekî encamek, tewra rêwîtiyek hêsan a çend girêkên cîran di darekê de dibe ku hewce bike ku serdana hejmareke berawirdî ya rûpelan bike. Ev pirsgirêkek e tewra gava ku em li ser bandorkeriya darên binary wekî avahiyek daneya bîranînê diaxivin, ji ber ku zivirandina domdar a rûpelan di cacheya pêvajoyê de ne kêfxweşiyek erzan e. Gava ku dor tê ku pir caran rûpelên ku bi nodên ji dîskê ve girêdayî ne, rewş bi tevahî dibe xemgînKoçgirî € <

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDBDarên B, ku pêşveçûnek darên binary in, pirsgirêkên ku di paragrafa berê de hatine destnîşan kirin çareser dikin. Ya yekem, ew bi xwe hevseng in. Ya duyemîn jî, her girêka wan komek bişkokên zarokan ne li 2, lê di binkomên rêzkirî yên M de vediqetîne, û hejmara M dikare pir mezin be, li ser fermana çend sed, an jî bi hezaran.

Bi vê rêyê:

  1. Her girêk hejmareke mezin ji mifteyên jixwe fermankirî dihewîne û dar jî pir kurt in.
  2. Dar taybetmendiya cîhê cîhê di bîranînê de werdigire, ji ber ku mifteyên ku bi nirxê nêzîk in bi xwezayî li kêleka hev li ser heman an jî girêkên cîran cih digirin.
  3. Dema ku di dema operasyona lêgerînê de ji darekê dadikevin, hejmara girêkên derbasbûnê kêm dibe.
  4. Hejmara girêkên armancê yên ku di dema pirsên rêzê de têne xwendin kêm dibe, ji ber ku her yek ji wan jixwe hejmareke mezin a bişkojkên fermankirî dihewîne.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

LMDB guhertoyek B-dara ku jê re dara B+ tê gotin bikar tîne da ku daneyan hilîne. Diagrama li jor sê celeb girêkên ku tê de hene nîşan dide:

  1. Li jor kok e. Ew ji têgeha databasek di hundurê depoyek de tiştek din pêk tîne. Di nav yek mînakek LMDB de, hûn dikarin çend databasên ku cîhê navnîşana virtual ya nexşekirî parve dikin biafirînin. Her yek ji wan ji koka xwe dest pê dike.
  2. Di asta herî jêrîn de pel hene. Ew û tenê ew cotên key-nirxê ku di databasê de hatine hilanîn dihewîne. Bi awayê, ev taybetmendiya darên B +-ê ye. Ger dara B-ya birêkûpêk di girêkên hemî astan de beşan binirxîne, wê hingê guhertoya B+ tenê di ya herî jêrîn de ye. Piştî ku vê rastiyê rast kir, em ê ji binê dara ku di LMDB-ê de tê bikar anîn bi tenê B-dara binav bikin.
  3. Di navbera kok û pelan de 0 an bêtir astên teknîkî yên bi girêkên navîgasyon (şax) hene. Karê wan ev e ku komek bişkojkên cûrbecûr di navbera pelan de parve bikin.

Ji hêla fizîkî ve, girêk blokên bîranînê yên dirêjahiya pêşwext in. Mezinahiya wan pirjimarek mezinahiya rûpelên bîranînê yên di pergala xebitandinê de ye, ku me li jor behs kir. Struktura nodê li jêr tê nîşandan. Sernav agahdariya meta vedihewîne, ya herî diyar ji bo nimûne kontrolê ye. Dûv re agahdarî li ser guheztinên ku hucreyên bi daneyê tê de ne tê. Heke em behsa girêkên navîgasyonê dikin, an jî di doza pelan de hemî cotên key-nirxê dipeyivin, dane dikarin bibin kilîtan.​ Hûn dikarin li ser strukturên rûpelan di xebatê de bêtir bixwînin. "Nirxandina Firotanên Kêl-Nirxê Bi Performansa Bilind".

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Piştî ku bi naveroka navxweyî ya girêkên rûpelan re mijûl bûn, em ê di forma jêrîn de dara B-ya LMDB bi rengek hêsan temsîl bikin.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Rûpelên bi girêk bi rêz li ser dîskê cih digirin. Rûpelên bi jimare yên bilind ber bi dawiya dosyayê ve ne. Di rûpela ku jê re tê gotin meta de agahdarî di derheqê dehfdanan de hene ku bi wan re kokên hemî daran têne dîtin. Dema ku pelek vedike, LMDB di lêgerîna rûpelek meta ya derbasdar de rûpel bi rûpel pelê ji serî heya serî digere û bi navgîniya wê databasên heyî dibîne.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Naha, xwedî ramanek li ser strukturên mentiqî û laşî yên rêxistina daneyê, em dikarin li ser stûna sêyemîn a LMDB-ê bisekinin. Ew bi alîkariya wê ye ku hemî guheztinên hilanînê bi danûstendinê û ji hevûdu veqetandî çêdibin, û databasê bi tevahî xwedan pirzimanî dide.

3.3. Whale #3. Kopî-li-nivîsandin

Hin operasyonên dara B-yê di nav girêkên wê de rêzek guhertinan pêk tîne. Mînakek lêzêdekirina mifteyek nû ye li girêkek ku berê gihîştiye kapasîteya xwe ya herî zêde. Di vê rewşê de, pêdivî ye ku yekem, girêk du parçe bikin, û ya duyemîn jî, girêdanek bi girêka zaroka nû ya di dêûbavê wê de zêde bikin. Ev prosedur potansiyel pir xeternak e. Ger ji ber hin sedeman (qeza, qutbûna elektrîkê, hwd.) tenê beşek ji guhertinên ji rêzê çêbibin, wê hingê dar dê di rewşek nehevgirtî de bimîne.

Yek çareseriyek kevneşopî ji bo çêkirina danûstendinek danûstendinek beredayî ev e ku meriv avahiyek daneya dîskê ya li tenişta B-dara zêde bike - têketinek danûstendinê, ku wekî têketinek pêş-nivîsandinê (WAL) jî tê zanîn. Ew pelek e ku di dawiya wê de operasyona armanckirî berî ku dara B bixwe biguhezîne bi hişkî hatî nivîsandin. Bi vî rengî, heke di dema xwe-naskirinê de xerabûna daneyê were tesbît kirin, databas bi têketinê dişêwire da ku xwe bi rêkûpêk bike.

LMDB wekî mekanîzmayek tolerasyona xeletiyê, bi navê kopî-li-nivîsandinê, rêbazek cûda hilbijartiye. Esasê wê ev e ku li şûna ku daneyên li ser rûpelek heyî nûve bike, ew pêşî wê bi tevahî kopî dike û di kopiyê de hemî guhertinan dike.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Dûv re, ji bo ku daneyên nûvekirî peyda bibin, pêdivî ye ku zencîreya girêka ku di girêka dêûbavê xwe de heyî biguhezîne. Ji ber ku ji bo vê yekê jî pêdivî ye ku were guheztin, ew jî berê tê kopî kirin. Pêvajo heta bi kokê vegerî berdewam dike. Tişta paşîn a ku were guheztin daneyên li ser rûpelê meta ye.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Ger di pêvajoya nûvekirinê de ji nişkê ve pêvajo têk bibe, wê hingê dê rûpelek meta ya nû neyê afirandin, an jî ew ê bi tevahî li ser dîskê neyê nivîsandin, û kontrolkirina wê dê xelet be. Di van her du rewşan de, rûpelên nû dê negihîjin, lê yên kevin dê bandor nebin. Ev hewcedariya LMDB-ê ji bo nivîsandina pêşnivîsa pêşîn ji bo domandina hevgirtina daneyan ji holê radike. De facto, strukturên hilanîna daneya li ser dîskê ku li jor hatî destnîşan kirin di heman demê de fonksiyona xwe digire. Nebûna têketinek danûstendinê ya eşkere yek ji taybetmendiyên LMDB ye ku leza xwendina daneya bilind peyda dike.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Sêwirana encam, ku jê re tenê-pêveka B-dara tê gotin, bi xwezayî veqetandina danûstendinê û pir-versiyonê peyda dike. Di LMDB-ê de, her danûstendina vekirî bi koka dara heyî ya têkildar re têkildar e. Heya ku danûstendin neqede, rûpelên dara ku bi wê ve girêdayî ne dê çu carî ji bo guhertoyên nû yên daneyê neyên guheztin an jî ji nû ve werin bikar anîn Bi vî rengî, hûn dikarin heya ku hûn dixwazin bi tevahî daneyên ku wê demê têkildar bûn bixebitin danûstendin hate vekirin, tevî ku hilanînê di vê demê de bi rengek çalak nûvekirina berdewam dike. Ev cewhera pirzimanî ye, ku LMDB ji bo hezkiriyên me çavkaniyek daneya îdeal dike UICollectionView. Piştî vekirina danûstendinek, ne hewce ye ku meriv şopa bîranîna serîlêdanê bi lez û bez derxistina daneyên heyî di nav hin avahiyek bîranînê de zêde bike, ji tirsa ku tiştek nemîne. Ev taybetmendî LMDB-ê ji heman SQLite-ê cuda dike, ku nikare bi vî rengî îzolasyonek tevahî pesnê xwe bide. Bi vekirina du danûstendinên di ya paşîn de û rakirina tomarek diyarkirî di nav yek ji wan de, dê êdî nekare heman tomarê di nav ya duyemîn de mayî bi dest bixe.

Aliyê drav ê drav karanîna potansiyel pir girîng a bîranîna virtual e. Slide destnîşan dike ku dê avahiya databasê çawa xuya bike heke ew bi hevdemî bi 3 danûstendinên xwendinê yên vekirî ve were guheztin ku li guhertoyên cihêreng ên databasê binêre. Ji ber ku LMDB nikare girêkên ku ji kokên ku bi danûstendinên heyî ve girêdayî ne ji nû ve bi kar bîne, firotgeh neçar e ku rayeka çaremîn a din di bîranînê de veqetîne û carek din rûpelên guhertî yên di binê wê de klon bike.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Li vir dê kêrhatî be ku hûn beşa pelên nexşeya bîranînê bi bîr bînin. Wusa dixuye ku vexwarina zêde ya bîranîna virtual divê me pir xemgîn neke, ji ber ku ew beşdarî şopa bîranîna serîlêdanê nake. Lêbelê, di heman demê de, hate destnîşan kirin ku iOS di veqetandina wê de pir hişk e, û em nekarin, mîna serverek an sermaseyê, herêmek LMDB ya 1 terabyte peyda bikin û qet li ser vê taybetmendiyê nefikirin. Ger gengaz be, divê hûn hewl bidin ku heyama danûstendinan bi qasî ku gengaz kurt bikin.

4. Sêwirana şemayek daneyê li ser API-ya key-nirxê

Werin em analîza xweya API-yê bi nihêrîna abstraksyonên bingehîn ên ku ji hêla LMDB ve hatî peyda kirin dest pê bikin: hawîrdor û databas, mift û nirx, danûstendin û nîşangiran.

Nîşeyek li ser navnîşên kodê

Hemî fonksiyonên di API-ya LMDB ya gelemperî de encama xebata xwe di forma kodek xeletiyê de vedigerînin, lê di hemî navnîşên paşerojê de verastkirina wê ji bo kurtbûnê tête paşde xistin.​ Di pratîkê de, me ya xwe jî bikar anî da ku bi depoyê re têkilî daynin. milêv C++ wrappers lmdbxx, ku tê de xeletî wekî îstîsnayên C++ têne çêkirin.

Wekî awayê bilez a girêdana LMDB bi projeyek ji bo iOS an macOS-ê, ez CocoaPod-a xwe pêşniyar dikim POSLMDB.

4.1. Abstractions bingehîn

Dor

avahiya MDB_env depoya rewşa navxweyî ya LMDB ye. Malbata fonksiyona pêşgir mdb_env destûrê dide te ku hûn hin taybetmendiyên wê mîheng bikin. Di rewşa herî hêsan de, destpêkirina motorê bi vî rengî xuya dike.

mdb_env_create(env);​
mdb_env_set_map_size(*env, 1024 * 1024 * 512)​
mdb_env_open(*env, path.UTF8String, MDB_NOTLS, 0664);

Di serîlêdana Mail.ru Cloud de, me nirxên xwerû yên tenê du parameteran guhert.

Ya yekem mezinahiya cîhê navnîşana virtual e ku pelê hilanînê pê re nexşandî ye. Mixabin, tewra li ser heman cîhazê jî, nirxa taybetî dikare ji xebitandinê heya xebitandinê pir cûda bibe. Ji bo ku vê taybetmendiya iOS-ê were hesibandin, hêjeya hilanînê ya herî zêde bi dînamîk tê hilbijartin. Ji nirxek diyar dest pê dike, ew bi rêzê heya fonksiyonê nîvî dibe mdb_env_open dê encamek cuda jê venegere ENOMEM. Di teorîyê de, rêyek berevajî jî heye - pêşî herî kêm bîranîn ji motorê re veqetînin, û dûv re, gava ku xelet têne wergirtin, MDB_MAP_FULL, zêde bike. Lêbelê, ew pir bêtir şîn e. Sedem ev e ku prosedûra ji nû ve veqetandina bîranînê (remap) bi karanîna fonksiyonê mdb_env_set_map_size hemî hebûnên (cursor, danûstandin, mift û nirx) ku berê ji motorê hatine wergirtin betal dike. Di kodê de hesabê vê zivirîna bûyeran dê bibe sedema tevliheviya wê ya girîng. Lêbelê, heke bîranîna virtual ji we re pir girîng e, wê hingê dibe ku ev bibe sedemek ku meriv ji nêzik ve li qalika ku pir pêş de çûye binêre. MDBX, li cihê ku di nav taybetmendiyên ragihandinê de "veguheztina mezinahiya databasa otomatîkî ya li ser-firînê" heye.

Parametreya duyemîn, nirxa xwerû ya ku ji me re ne xweş e, mekanîzmaya dabînkirina ewlehiya têxê rê dide. Mixabin, bi kêmî ve iOS 10 bi piştgirîkirina hilanîna herêmî ya mijarê re pirsgirêk hene. Ji ber vê yekê, di mînaka jorîn de, depo bi ala ve tê vekirin MDB_NOTLS. Li gel vê jî pêwîst bû milêv C++ wrapper lmdbxxji bo qutkirina guherbarên bi vê taybetmendiyê û tê de.

Databases

Database mînakek dara B-ya cihê ye, ku me li jor nîqaş kir. Vekirina wê di hundurê danûstendinek de pêk tê, ku dibe ku di destpêkê de hinekî xerîb xuya bike.

MDB_txn *txn;​
MDB_dbi dbi;​
mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);​
mdb_dbi_open(txn, NULL, MDB_CREATE, &dbi);​
mdb_txn_abort(txn);

Bi rastî, danûstendinek di LMDB de saziyek hilanînê ye, ne saziyek databasek taybetî ye. Ev têgeh dihêle hûn li ser saziyên ku di databasên cihêreng de ne, operasyonên atomî pêk bînin. Di teorîyê de, ev îhtîmala modelkirina tabloyên di forma databasên cihêreng de vedike, lê di demekê de min rêyek cûda girt, ku li jêr bi hûrgulî hatî vegotin.

Keys û nirxên

avahiya MDB_val têgeha hem key û hem jî nirx model dike. Depo di derbarê semantîka wan de nizane. Ji bo wê, tiştek din tenê rêzek baytên bi pîvanek diyarkirî ye. Mezinahiya kilîtê ya herî zêde 512 byte ye.

typedef struct MDB_val {​
    size_t mv_size;​
    void *mv_data;​
} MDB_val;​​

Bi karanîna berhevkarek, firotgeh mifteyan bi rêza hilkişînê rêz dike. Heke hûn wê bi ya xwe neguhezînin, wê hingê ya xwerû dê were bikar anîn, ku wan li gorî rêza ferhengî bayt-byte rêz dike.

Transactions

Struktura danûstendinê di nav de bi hûrgulî tête diyar kirin beşa berê, ji ber vê yekê li vir ez ê bi kurtasî taybetmendiyên wan ên sereke dubare bikim:

  1. Hemî taybetmendiyên bingehîn piştgirî dike TIRŞ: atomîbûn, pêkvebûn, veqetandin û pêbawerî. Ez nikarim ji bîr bikim ku di macOS û iOS-ê de di warê domdariyê de xeletiyek heye ku di MDBX de hate rast kirin. Hûn dikarin di wan de bêtir bixwînin BIXWÎNE.
  2. Nêzîkatiya pirtextkirinê ji hêla nexşeya "nivîskarek yek / pir xwendevan" ve tête diyar kirin. Nivîskar hevdu asteng dikin, lê xwendevanan asteng nakin. Xwendevan ne nivîskaran û ne jî hevdu asteng dikin.
  3. Piştgiriya ji bo danûstandinên hêlînê.
  4. Piştgiriya Multiversion.

Multiversion di LMDB de ew qas baş e ku ez dixwazim wê di çalakiyê de destnîşan bikim. Ji koda jêrîn hûn dikarin bibînin ku her danûstendin bi tam guhertoya databasê ya ku di dema vekirina wê de heyî kar dike, ji hemî guhertinên paşîn bi tevahî veqetandî ye. Destpêkirina hilanînê û lê zêdekirina tomarek testê li ser wê tiştek balkêş temsîl nake, ji ber vê yekê ev rîtuel di binê xerakirinê de têne hiştin.

Zêdekirina navnîşek testê

MDB_env *env;
MDB_dbi dbi;
MDB_txn *txn;

mdb_env_create(&env);
mdb_env_open(env, "./testdb", MDB_NOTLS, 0664);

mdb_txn_begin(env, NULL, 0, &txn);
mdb_dbi_open(txn, NULL, 0, &dbi);
mdb_txn_abort(txn);

char k = 'k';
MDB_val key;
key.mv_size = sizeof(k);
key.mv_data = (void *)&k;

int v = 997;
MDB_val value;
value.mv_size = sizeof(v);
value.mv_data = (void *)&v;

mdb_txn_begin(env, NULL, 0, &txn);
mdb_put(txn, dbi, &key, &value, MDB_NOOVERWRITE);
mdb_txn_commit(txn);

MDB_txn *txn1, *txn2, *txn3;
MDB_val val;

// Открываем 2 транзакции, каждая из которых смотрит
// на версию базы данных с одной записью.
mdb_txn_begin(env, NULL, 0, &txn1); // read-write
mdb_txn_begin(env, NULL, MDB_RDONLY, &txn2); // read-only

// В рамках первой транзакции удаляем из базы данных существующую в ней запись.
mdb_del(txn1, dbi, &key, NULL);
// Фиксируем удаление.
mdb_txn_commit(txn1);

// Открываем третью транзакцию, которая смотрит на
// актуальную версию базы данных, где записи уже нет.
mdb_txn_begin(env, NULL, MDB_RDONLY, &txn3);
// Убеждаемся, что запись по искомому ключу уже не существует.
assert(mdb_get(txn3, dbi, &key, &val) == MDB_NOTFOUND);
// Завершаем транзакцию.
mdb_txn_abort(txn3);

// Убеждаемся, что в рамках второй транзакции, открытой на момент
// существования записи в базе данных, её всё ещё можно найти по ключу.
assert(mdb_get(txn2, dbi, &key, &val) == MDB_SUCCESS);
// Проверяем, что по ключу получен не абы какой мусор, а валидные данные.
assert(*(int *)val.mv_data == 997);
// Завершаем транзакцию, работающей хоть и с устаревшей, но консистентной базой данных.
mdb_txn_abort(txn2);

Ez pêşniyar dikim ku hûn bi SQLite re heman hîleyê biceribînin û bibînin ka çi diqewime.

Multiversion feydeyên pir xweş ji jiyana pêşdebirek iOS re tîne. Bi karanîna vê taybetmendiyê, hûn dikarin bi hêsanî û xwezayî rêjeya nûvekirina çavkaniya daneyê ji bo formên ekranê, li ser bingeha ramanên ezmûna bikarhêner rast bikin. Mînakî, ka em taybetmendiyek serîlêdana Cloud Mail.ru, wekî otobarkirina naverokê ji galeriya medyaya pergalê, bigirin. Bi pêwendiyek baş, xerîdar dikare di her çirkeyê de çend wêneyan li serverê zêde bike. Ger hûn piştî her dakêşandinê nûve bikin UICollectionView digel naveroka medyayê ya di ewrê bikarhêner de, hûn dikarin di vê pêvajoyê de 60 fps ji bîr bikin û bişoxilînin. Ji bo pêşî li nûvekirinên pir caran ekranê bigirin, hûn hewce ne ku bi rengekî rêjeya ku daneya di binê bingehîn de diguhezîne sînordar bikin UICollectionViewDataSource.

Heke databas piştgirî nede pirguhertoyê û destûrê dide te ku hûn tenê bi rewşa heyî re bixebitin, wê hingê ji bo afirandina wêneyek dem-stabil a daneyê hûn hewce ne ku wê li hin strukturên daneya bîranînê an jî li tabloyek demkî kopî bikin. Yek ji van nêzîkatiyan pir biha ye. Di mijara hilanîna nav-bîrê de, em hem di bîranînê de, hem ji hêla hilanîna tiştên çêkirî ve têne çêkirin, hem jî bi demê re, bi veguhertinên ORM-ê yên zêde ve girêdayî ye, lêçûn digirin. Di derbarê tabloya demkî de, ev kêfxweşiyek hê bihatir e, ku tenê di rewşên ne-tewre de têgihîştî ye.

Çareseriya pirzimanî ya LMDB pirsgirêka domandina çavkaniyek daneya aram bi rengek pir xweşik çareser dike. Tenê vekirina danûstendinek û voila bes e - heya ku em wê temam bikin, mîhenga daneyê garantî ye ku were rast kirin. Mantiqa leza nûvekirina wê naha bi tevahî di destê qata pêşandanê de ye, bêyî sermaya çavkaniyên girîng.

Cursors

Cursors mekanîzmayek ji bo dubarekirina birêkûpêk li ser cotên key-nirxê bi navgîniya dara B-yê re peyda dikin. Bêyî wan, ne mimkun e ku meriv tabloyên di databasê de bi bandor model bike, ya ku em nuha vedigerin.

4.2. Table Modeling

Taybetmendiya rêzkirina mifteyê destûrê dide te ku hûn abstrakasyonek astek bilind wekî tabloyek li ser jorînên bingehîn ava bikin. Ka em vê pêvajoyê bi mînaka tabloya sereke ya xerîdarek cloudê binirxînin, ku agahdariya li ser hemî pel û peldankên bikarhêner vedigire.

Schema sifrê

Yek ji senaryoyên hevpar ên ku divê avahiyek tabloyê ya bi dara peldankê were çêkirin, hilbijartina hemî hêmanên ku di nav pelrêça diyarkirî de ne Modelek rêxistina daneyê ya baş e ji bo pirsên bi vî rengî Lîsteya cîrantiyê. Ji bo bicihanîna wê li ser hilanîna key-nirxê, pêdivî ye ku bişkojkên pel û peldankan bi vî rengî werin rêz kirin ku ew li gorî endametiya xwe di pelrêça dêûbav de werin kom kirin. Digel vê yekê, ji bo ku hûn naveroka pelrêçê bi forma ku ji bikarhênerek Windows-ê re naskirî nîşan bidin (pêşîn peldank, dûv re pelan, her du jî bi alfabetîk hatine rêz kirin), pêdivî ye ku qadên pêvek ên têkildar di mifteyê de bihewînin.

Wêneya jêrîn nîşan dide ku, li ser bingeha peywira ku di dest de ye, çawa dibe ku nûnertiya kilîtan bi rengek rêzek byte xuya bike. Bîteyên bi nasnavê pelrêça dêûbav (sor) pêşî, paşê bi tîpa (kesk) û di dûvikê de bi navî (şîn) têne rêz kirin awayê pêwîst. Veguhastina birêkûpêk a bişkojkên bi heman pêşgira sor nirxên wan ên têkildar bi rêza ku divê ew di navgîniya bikarhênerê de (li milê rastê) werin xuyang kirin, bêyî ku hewcedariya paş-pêvajoya zêde hewce bike, dide me.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Serializing Keys û Nirxên

Li cîhanê gelek rêbazên ji bo rêzkirina tiştan hatine îcadkirin. Ji ber ku ji bilî bileziyê pêdiviya me ya din tunebû, me ji xwe re ya herî zû ya gengaz hilbijart - qutiyek ji bîra ku ji hêla mînakek avahiya zimanê C ve hatî dagir kirin Bi vî rengî, mifteya hêmanek pelrêça dikare bi strukturek jêrîn were model kirin NodeKey.

typedef struct NodeKey {​
    EntityId parentId;​
    uint8_t type;​
    uint8_t nameBuffer[256];​
} NodeKey;

Ji bo rizgarkirina NodeKey di hilanînê de ku di objektê de hewce ye MDB_val nîşana daneyê li navnîşana destpêka avahîsaziyê bi cih bikin, û mezinahiya wan bi fonksiyonê hesab bikin sizeof.

MDB_val serialize(NodeKey * const key) {
    return MDB_val {
        .mv_size = sizeof(NodeKey),
        .mv_data = (void *)key
    };
}

Di beşa yekem a li ser pîvanên hilbijartina databasê de, min behsa kêmkirina veqetandinên dînamîkî yên di nav operasyonên CRUD de wekî faktorek girîng a hilbijartinê kir. Koda fonksiyonê serialize nîşan dide ku di doza LMDB-ê de ew çawa dikarin bi tevahî werin dûr xistin dema ku tomarên nû di databasê de têxin. Rêzeya baytê ya ku ji serverê tê pêşî di strukturên stackê de tê guheztin, û dûv re ew bi sivikî têne avêtin hilanînê. Bihesibînin ku di hundurê LMDB-ê de veqetandinên dînamîkî jî tune, hûn dikarin ji hêla standardên iOS-ê ve rewşek fantastîk bistînin - tenê bîranîna stack bikar bînin da ku li seranserê riya ji torê heya dîskê bi daneyan re bixebitin!

Bi berhevkarek binary re rêzkirina mifteyan

Têkiliya rêza sereke ji hêla fonksiyonek taybetî ya ku jê re berhevkar tê gotin tête diyar kirin. Ji ber ku motor di derheqê semantîka baytên ku di nav wan de ne tiştek nizane, berawirdkarê xwerû neçar e ku bişkokan li gorî rêza ferhengografî rêz bike, serî li berhevdana byte-bi-byte bide. Bikaranîna wê ji bo birêxistinkirina avahiyan dişibihe tiraştina bi axînek jêkirin. Lêbelê, di rewşên hêsan de ez vê rêbazê qebûl dikim. Alternatîv li jêr tê ravekirin, lê li vir ez ê çend rakêşên ku li ser vê rêyê belav bûne destnîşan bikim.

Yekem tiştê ku tê bîra meriv nûnertiya bîranînê ya celebên daneya seretayî ye. Bi vî rengî, li ser hemî cîhazên Apple-ê, guhêrbarên yekjimar di formatê de têne hilanîn Little Endian. Ev tê wê wateyê ku byte-ya herî hindik girîng dê li milê çepê be, û dê nekare bi karanîna berhevokek byte-bi-byte jimareyên bêkêmasî bi rêz bike. Mînakî, hewldana kirina vê yekê bi komek hejmarên ji 0 heya 511-an dê encama jêrîn derxe holê.

// value (hex dump)
000 (0000)
256 (0001)
001 (0100)
257 (0101)
...
254 (fe00)
510 (fe01)
255 (ff00)
511 (ff01)

Ji bo çareserkirina vê pirsgirêkê, pêdivî ye ku hejmarên bêkêmasî di mifteyê de di formatek ku ji bo berhevkara byte-byte re guncaw e werin hilanîn. Fonksiyonên ji malbatê dê ji we re bibin alîkar ku hûn veguherîna pêwîst pêk bînin hton* (gelek rindik htons ji bo hejmarên du-byte yên nimûne).

Formata temsîlkirina rêzan di bernamekirinê de, wekî ku hûn dizanin, tevahiyek e dîrok. Ger semantîka rêzan, û hem jî şîfrekirina ku ji bo temsîlkirina wan di bîranînê de tê bikar anîn, destnîşan dike ku dibe ku ji her karakterek ji yek byte zêdetir be, wê hingê çêtir e ku meriv tavilê dev ji ramana karanîna berhevkarek xwerû berde.

Tişta duyemîn ku divê di hişê xwe de bimîne ev e prensîbên hevgirtinê berhevkarê qada strukturê. Ji ber wan, bytes bi nirxên zibil dikarin di bîranînê de di navbera qadan de bêne çêkirin, ku, bê guman, dabeşkirina byte-byte dişkîne. Ji bo rakirina çopê, hûn hewce ne ku qadan bi rêzek hişk diyar bikin, qaîdeyên hevrêziyê li ber çavan bigirin, an jî taybetmendiyê di danezana strukturê de bikar bînin. packed.

Bi berhevkarek derveyî re bişkojkan ferman dikin

Dibe ku mantiqa berhevdana sereke ji bo berhevkarek binar pir tevlihev be. Yek ji gelek sedeman hebûna qadên teknîkî di nav avahiyan de ye. Ez ê rûdana wan bi mînakek mifteyek ji bo hêmanek pelrêça ku jixwe ji me re nas e destnîşan bikim.

typedef struct NodeKey {​
    EntityId parentId;​
    uint8_t type;​
    uint8_t nameBuffer[256];​
} NodeKey;

Tevî sadebûna wê, di pirraniya bûyeran de ew pir bîranîn dixwe. Tampona navê 256 byte digire, her çend bi navînî navên pel û peldankan kêm caran ji 20-30 tîpan derbas dibin.

Yek ji teknîkên standard ên ji bo xweşbînkirina mezinahiya tomarê ev e ku meriv wê li mezinahiya rastîn "birûs bike". Esasê wê ev e ku naveroka hemî qadên bi dirêjahiya guhêrbar di dawiya avahîsaziyê de di tamponek de têne hilanîn, û dirêjahiya wan di guhêrbarên cihê de têne hilanîn. NodeKey wiha tê guherandin.

typedef struct NodeKey {​
    EntityId parentId;​
    uint8_t type;​
    uint8_t nameLength;​
    uint8_t nameBuffer[256];​
} NodeKey;

Wekî din, dema serialîzekirinê, mezinahiya daneyê nayê diyar kirin sizeof tevahiya avahî, û mezinahiya hemî qadan dirêjiyek sabît e û ji bilî mezinahiya beşa tamponê ya bi rastî hatî bikar anîn e.

MDB_val serialize(NodeKey * const key) {
    return MDB_val {
        .mv_size = offsetof(NodeKey, nameBuffer) + key->nameLength,
        .mv_data = (void *)key
    };
}

Di encama refaktorkirinê de, me di cîhê ku ji hêla keys ve hatî dagir kirin de teserifên girîng wergirtin. Lêbelê, ji ber qada teknîkî nameLength, berawirdkara binaryê ya xwerû êdî ji bo berhevdana mifteyê ne guncaw e. Ger em wê bi ya xwe neguhezînin, wê hingê dirêjiya nav dê ji nav xwe ve di veqetandinê de faktorek pêşîntir be.

LMDB destûrê dide her databasê ku fonksiyona xweya berhevoka sereke hebe. Ev bi karanîna fonksiyonê tête kirin mdb_set_compare bi hişkî berî vebûnê. Ji ber sedemên diyar, ew di tevahiya jiyana databasê de nayê guhertin. Berawirdkar du kilîtan di formata binary de wekî têketinê distîne, û di dergehê de encama berhevdanê vedigerîne: ji (-1) kêmtir, ji (1) mezintir an jî wekhev (0). Pseudocode ji bo NodeKey wisa xuya dike.

int compare(MDB_val * const a, MDB_val * const b) {​
    NodeKey * const aKey = (NodeKey * const)a->mv_data;​
    NodeKey * const bKey = (NodeKey * const)b->mv_data;​
    return // ...
}​

Heya ku hemî bişkokên di databasê de ji heman celebê ne, avêtina bê şert û merc nûnertiya wan a baytê li ser celebê strukturê mifteya serîlêdanê qanûnî ye. Li vir yek nuwaze heye, lê ew ê li jêr di binbeşa "Qeydên Xwendinê" de were nîqaş kirin.

Serializing Nirxên

LMDB bi bişkojkên tomarên tomarkirî re pir zexm dixebite. Berhevdana wan bi hevûdu re di çarçoveya her operasyona serîlêdanê de pêk tê, û performansa tevahî çareseriyê bi leza berhevkarê ve girêdayî ye. Di cîhanek îdeal de, berhevkara binar a xwerû divê têra berhevkirina mifteyan be, lê heke we pêdivî bû ku hûn yên xwe bikar bînin, wê hingê divê prosedûra ji bo deserialîzekirina mifteyên tê de bi qasî ku gengaz be.

Database bi taybetî bi beşa nirxa tomarê (nirx) re eleqedar nabe. Veguheztina wê ji nûneriya byte-ê ji tiştekê re tenê gava ku ew jixwe ji hêla koda serîlêdanê ve tê xwestin pêk tê, mînakî, ku wê li ser ekranê nîşan bide. Ji ber ku ev kêm kêm diqewime, hewcedariyên bilez ji bo vê prosedurê ne ew qas krîtîk in, û di pêkanîna wê de em pir azad in ku li ser rehetiyê bisekinin Mînakî, ji bo serialîzekirina metadata di derbarê pelên ku hîn nehatine dakêşandin, em bikar tînin NSKeyedArchiver.

NSData *data = serialize(object);​
MDB_val value = {​
    .mv_size = data.length,​
    .mv_data = (void *)data.bytes​
};

Lêbelê, carinan hene ku performans hîn jî girîng e. Mînakî, dema ku metaformasyonê di derheqê strukturek pelê ya ewr a bikarhêner de hildibijêre, em heman avêtina bîranînê ya tiştan bikar tînin. Girîngiya peywira afirandina nûnertiyek rêzkirî ya wan ev e ku hêmanên pelrêçek ji hêla hiyerarşiyek çînan ve têne model kirin.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Ji bo cîbicîkirina wê di zimanê C de, qadên taybetî yên mîratxweran di strukturên cihê de têne danîn, û girêdana wan bi bingehê re bi qada yekîtiyê ya celebê ve tête diyar kirin. Naveroka rastîn a yekîtiyê bi celebê taybetmendiya teknîkî ve têne diyar kirin.

typedef struct NodeValue {​
    EntityId localId;​
    EntityType type;​
    union {​
        FileInfo file;​
        DirectoryInfo directory;​
    } info;​
    uint8_t nameLength;​
    uint8_t nameBuffer[256];​
} NodeValue;​

Zêdekirin û nûvekirina tomaran

Mifteya serialîzekirî û nirx dikare li dikanê were zêdekirin. Ji bo vê yekê, fonksiyonê bikar bînin mdb_put.

// key и value имеют тип MDB_val​
mdb_put(..., &key, &value, MDB_NOOVERWRITE);

Di qonaxa veavakirinê de, hilanînê dikare bi heman mifteyê destûr an qedexekirina tomarkirina gelek tomaran hebe, heke dubarekirina kilîtan qedexe ye, wê hingê dema ku tomarek têxin, hûn dikarin diyar bikin ka nûvekirina tomarek heyî destûr e an na. Ger şikestin tenê di encama xeletiyek kodê de çêbibe, wê hingê hûn dikarin bi destnîşankirina ala xwe ji wê biparêzin. NOOVERWRITEKoçgirî € <

Xwendina navnîşan

Ji bo xwendina tomarên di LMDB de, fonksiyonê bikar bînin mdb_get. Ger cotê key-nirx ji hêla strukturên berê ve hatî avêtin ve were temsîl kirin, wê hingê ev prosedur bi vî rengî xuya dike.

NodeValue * const readNode(..., NodeKey * const key) {​
    MDB_val rawKey = serialize(key);​
    MDB_val rawValue;​
    mdb_get(..., &rawKey, &rawValue);​
    return (NodeValue * const)rawValue.mv_data;​
}

Navnîşa pêşkêşkirî destnîşan dike ka çawa serialîzasyon bi navgîniya avêtina strukturê dihêle hûn ne tenê dema nivîsandinê, lê dema xwendina daneyan jî ji veqetandinên dînamîkî xilas bibin. Ji fonksiyonê hatî mdb_get nîşanker tam li navnîşana bîranîna virtual dinêre ku databas nûneriya byte ya objektê diparêze. Bi rastî, em celebek ORM-ê digirin ku leza xwendina daneya pir zêde hema hema belaş peyda dike. Tevî hemî bedewiya nêzîkbûnê, pêdivî ye ku meriv çend taybetmendiyên wê bi bîr bîne.

  1. Ji bo danûstendinek tenê xwendinê, nîşana avahiya nirxê garantî ye ku heya ku danûstendin neyê girtin tenê derbasdar bimîne. Wekî ku berê hate destnîşan kirin, rûpelên dara B-ya ku tiştek li ser tê de ye, bi saya prensîba kopî-li-nivîsandinê, heya ku ew bi kêmî ve yek danûstendinê ve têne referans kirin nayên guhertin. Di heman demê de, gava ku danûstendina paşîn a ku bi wan re têkildar be temam dibe, rûpel dikarin ji bo daneyên nû ji nû ve werin bikar anîn. Ger hewce be ku tişt ji danûstendina ku wan çêkiriye sax bimînin, wê hingê divê ew hîn jî bêne kopî kirin.
  2. Ji bo danûstendinek xwendinê, nîşana avahiya nirxa encam dê tenê heya pêvajoya yekem a guheztinê (nivîsandin an jêbirina daneyan) derbasdar be.
  3. Tevî ku avahiya NodeValue ne bêkêmasî, lê birêkûpêk (binihêre beşa "Serdarkirina bişkokan bi karanîna berhevkarek derveyî"), hûn dikarin bi ewlehî bi rêgezê bigihîjin zeviyên wê. Ya sereke ev e ku meriv wê neguhezîne!
  4. Di bin ti şert û mercan de divê avahî bi riya nîşankera wergirtî neyê guhertin. Divê hemî guhertin tenê bi rêbazê bêne kirin mdb_put. Lêbelê, her çend hûn dixwazin vê yekê bikin jî, ew ê ne mumkun be, ji ber ku devera bîranînê ya ku ev avahî lê ye di moda tenê xwendinê de nexşe ye.
  5. Ji bo nimûne, bi karanîna fonksiyonê mezinahiya hilanînê ya herî zêde zêde bikin, pelek li cîhê navnîşana pêvajoyê ji nû ve bikin mdb_env_set_map_size bi gelemperî hemî danûstendin û saziyên têkildar bi tevahî betal dike û bi taybetî hin tiştan destnîşan dike.

Di dawiyê de, taybetmendiyek din ew qas xapînok e ku eşkerekirina cewhera wê tenê di paragrafek din de cîh nagire. Di beşa li ser dara B de, min nexşeyek da ku rûpelên wê di bîranînê de çawa hatine rêz kirin. Ji vê yekê derdikeve ku navnîşana destpêka tamponê bi daneyên serialîzekirî dikare bêkêmasî kêfî be. Ji ber vê yekê, nîşana wan di avahiyê de wergirt MDB_val û ji bo nîşanek li ser avahiyek kêm dibe, ew di rewşa giştî de nelihev dibe. Di heman demê de, mîmariya hin çîpên (di doza iOS-ê de ev armv7 e) hewce dike ku navnîşana her daneyê ji mezinahiya peyva makîneyê pirjimar be an, bi gotinek din, mezinahiya bit ya pergalê ( ji bo armv7 ew 32 bit e). Bi gotineke din, operasyoneke mîna *(int *foo)0x800002 li ser wan revîn e û bi biryarekê dibe sedema îdamê EXC_ARM_DA_ALIGN. Du rê hene ku meriv ji çarenûsek wusa xemgîn dûr bikeve.

Ya yekem bi kopîkirina pêşîn a daneyan di nav avahiyek eşkere hevgirtî de vedigire. Mînakî, li ser berhevkarek xwerû ev ê wekî jêrîn were xuyang kirin.

int compare(MDB_val * const a, MDB_val * const b) {
    NodeKey aKey, bKey;
    memcpy(&aKey, a->mv_data, a->mv_size);
    memcpy(&bKey, b->mv_data, b->mv_size);
    return // ...
}

Rêyek alternatîf ev e ku meriv pêşwext ji berhevkerê re agahdar bike ku dibe ku strukturên nirx-kilît neyên rêz kirin. aligned(1). Li ser ARM hûn dikarin heman bandorê bikin gîhaştin û taybetmendiya pakkirî bikar bînin. Bifikirin ku ew di heman demê de ji bo xweşbînkirina cîhê ku ji hêla strukturê ve hatî dagir kirin jî dibe alîkar, ev rêbaz ji min re bijartir xuya dike, her çend pirtûk ji bo zêdebûna lêçûna operasyonên gihîştina daneyê.

typedef struct __attribute__((packed)) NodeKey {
    uint8_t parentId;
    uint8_t type;
    uint8_t nameLength;
    uint8_t nameBuffer[256];
} NodeKey;

Pirsên rêzê

Ji bo dubarekirina li ser komek tomaran, LMDB abstrakasyonek kursor peyda dike. Ka em binihêrin ka meriv çawa bi wê re bi karanîna mînaka tabloyek bi metadata cloudê ya bikarhêner ku ji berê ve ji me re nas e re dixebite.

Wekî beşek ji nîşandana navnîşek pelan di pelrêçekê de, pêdivî ye ku meriv hemî kilîtên ku pel û peldankên wê yên zarok pê re têkildar in bibînin. Di beşên berê de me kilîtan rêz kirin NodeKey wisa ku ew di serî de bi nasnameya pelrêça dêûbav têne ferman kirin. Bi vî rengî, ji hêla teknîkî ve, peywira wergirtina naveroka peldankek bi danîna nîşanderê li ser sînorê jorîn a koma bişkojan bi pêşgirek diyarkirî û dûv re dubarekirina sînorê jêrîn tê.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Sînorê jorîn rasterast ji hêla lêgerîna rêzdar ve tê dîtin. Ji bo kirina vê yekê, nîşanker li destpêka tevahiya navnîşa bişkojkên databasê tê danîn û heya ku mifteyek bi nasnavê pelrêça dêûbavê li binê wê xuya bibe tê zêdekirin. Vê rêbazê 2 kêmasiyên eşkere hene:

  1. Tevliheviya lêgerîna xêzkirî, her çend, wekî ku tê zanîn, di daran de bi gelemperî û di dara B de bi taybetî ew dikare di dema logarîtmîkî de were kirin.
  2. Bêdeng, hemî rûpelên berî yê ku tê xwestin ji pelê berbi bîra sereke, ku pir biha ye, têne rakirin.

Xweşbextane, LMDB API rêyek bi bandor peyda dike ku di destpêkê de nîşanderê bi cîh bike Ji bo vê yekê, hûn hewce ne ku mifteyek ku nirxa wê eşkere ji mifteya ku li sînorê jorîn a navberê ye biafirînin. Mînakî, têkildarî navnîşa di jimareya jor de, em dikarin mifteyek ku tê de zeviyê tê de çêbikin parentId dê bibe 2 û hemî yên mayî bi sifiran têne dagirtin. Bişkojek wusa bi qismî dagirtî ji têketina fonksiyonê re tê peyda kirin mdb_cursor_get operasyonê nîşan dide MDB_SET_RANGEKoçgirî € <

NodeKey upperBoundSearchKey = {​
    .parentId = 2,​
    .type = 0,​
    .nameLength = 0​
};​
MDB_val value, key = serialize(upperBoundSearchKey);​
MDB_cursor *cursor;​
mdb_cursor_open(..., &cursor);​
mdb_cursor_get(cursor, &key, &value, MDB_SET_RANGE);

Ger sînorê jorîn ê komek kilîtan were dîtin, wê gavê em li ser wê dubare dikin heya ku em hev bibînin an miftek din bigihîje hev. parentId, an jî kilît dê qet neqedin.

do {​
    rc = mdb_cursor_get(cursor, &key, &value, MDB_NEXT);​
    // processing...​
} while (MDB_NOTFOUND != rc && // check end of table​
         IsTargetKey(key));    // check end of keys group​​

Tiştê xweş ev e ku wekî beşek ji dubarekirinê bi karanîna mdb_cursor_get, em ne tenê mifteyê, lê di heman demê de nirx jî digirin. Ger, ji bo bicîhanîna şert û mercên nimûneyê, hûn hewce ne ku, di nav tiştên din de, zeviyên ji beşa nirxa tomarê kontrol bikin, wê hingê ew bêyî tevgerên zêde têne gihîştin.

4.3. Modelkirina têkiliyên di navbera tabloyan de

Heya nuha, me karî em hemî aliyên sêwirandin û xebata bi databasek yek-tabloyê re bifikirin. Em dikarin bibêjin ku tablo komek tomarên birêkûpêk e ku ji heman celeb cotên key-nirx pêk tê. Ger hûn miftekê wekî çargoşeyekê û nirxa têkildar wekî parallelepiped nîşan bidin, hûn diyagramek dîtbar a databasê distînin.

To

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Lêbelê, di jiyana rastîn de kêm kêm gengaz e ku meriv bi xwînrijandina hindik re derbas bibe. Bi gelemperî di danegehekê de, yekem hewce ye ku çend tablo hebin, û ya duyemîn jî, di wan de bi rêzek ji mifteya bingehîn cûda bijartinan bikin. Ev beşa dawî ji bo mijarên afirandin û girêdana wan veqetandî ye.

Tabloyên Indeks

Serlêdana ewr beşa "Galerî" heye. Ew naveroka medyayê ji tevahiya ewr nîşan dide, li gorî tarîxê hatî veqetandin. Ji bo pêkanîna bijarek wusa çêtirîn, li kêleka tabloya sereke hûn hewce ne ku yeka din bi celebek nû ya bişkojkan biafirînin. Ew ê zeviyek bi dîroka ku pelê hatî afirandin vehewînin, ku dê wekî pîvana dabeşkirina bingehîn tevbigere. Ji ber ku bişkojkên nû heman daneyan wekî bişkojkên di tabloya sereke de vedibêjin, ji wan re bişkojkên nîşankirinê têne gotin. Di wêneya jêrîn de ew bi porteqalî têne xuyang kirin.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Ji bo ku mifteyên tabloyên cihêreng di nav heman databasê de ji hev veqetînin, tabloyek qada teknîkî ya din li hemîyan hate zêdekirin. Bi çêkirina wê ya herî pêşîn ji bo veqetandinê, em ê bigihîjin komkirina mifteyan pêşî li gorî tabloyan, û di nav tabloyan de - li gorî qaîdeyên xwe.​

Mifteya indexê heman daneyê wekî mifteya bingehîn vedigire. Pêkanîna rasterast a vê taybetmendiyê bi girêdana bi wê re kopiyek ji beşa nirxê ya sereke ya bingehîn ji çend xalan ve ne çêtirîn e:

  1. Di warê cîhê ku hatî girtin de, metadata dikare pir dewlemend be.
  2. Ji hêla performansê ve, ji ber ku dema ku metadata girêkek nûve dike, hûn neçar in ku wê bi karanîna du bişkokan ji nû ve binivîsin.
  3. Ji hêla piştgiriya kodê ve, heke em ji bîr nekin ku daneyan ji bo yek ji kilît nûve bikin, em ê di hilanînê de xeletiyek neyekseriya daneyê bistînin.

Paşê, em ê bifikirin ka meriv çawa van kêmasiyan ji holê rake.

Rêxistinkirina têkiliyên di navbera maseyan

Nimûne ji bo girêdana tabloya navnîşê bi tabloya sereke re baş e "key wek nirx". Wekî ku navê wê diyar dike, beşa nirxê qeyda pêvekê kopiyek nirxa sereke ya sereke ye. Ev nêzîkatî hemî dezawantajên jorîn ên ku bi hilanîna kopiyek beşa nirxê ya tomara bingehîn ve girêdayî ne, ji holê radike. Tenê lêçûn ev e ku ji bo bidestxistina nirxek bi mifteya navnîşê, hûn hewce ne ku li şûna yekê 2 pirsan ji databasê re bikin. Skematîkî, şemaya databasa encam bi vî rengî xuya dike.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Nimûneyek din a ji bo birêxistinkirina têkiliyên di navbera tabloyan de ye "mifteya zêde". Esasê wê ev e ku taybetmendiyên din li mifteyê zêde bike, yên ku ne ji bo birêkûpêk, lê ji bo ji nû ve çêkirina mifteya têkildar hewce ne Di serîlêdana Mail.ru Cloud de mînakên rastîn ên karanîna wê hene, lêbelê, ji bo ku hûn nekevin hundurê kûr. di çarçoveya çarçoveyên taybetî yên iOS-ê de, ez ê mînakek xeyalî, lê mînakek zelaltir bidim.

Xerîdarên mobîl Cloud rûpelek heye ku hemî pel û peldankên ku bikarhêner bi kesên din re parve kiriye nîşan dide. Ji ber ku dosyayên bi vî rengî bi nisbet kêm in, û gelek celeb agahdariya taybetî ya di derbarê ragihandinê de bi wan ve girêdayî hene (kê destûr tê dayîn, bi kîjan mafan re, hwd.), dê ne maqûl be ku meriv beşa nirxê giran bike. bi wê re di tabloya sereke de tomar bikin. Lêbelê, heke hûn dixwazin pelên weha offline nîşan bidin, hûn hîn jî hewce ne ku wê li cîhek hilînin. Çareseriya xwezayî ew e ku ji bo wê tabloyek veqetandî were çêkirin. Di diagrama jêrîn de, mifteya wê bi "P" ve tê pêşgirkirin, û cîhgira "propname" dikare bi nirxa taybetî "agahdariya gelemperî" were guheztin.​

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Hemî metadaneyên bêhempa, ji bo hilanîna ku tabloyek nû hatî çêkirin, di beşa nirxa tomarê de têne danîn. Di heman demê de, hûn naxwazin daneyên li ser pel û peldankên ku berê di tabloya sereke de hatine hilanîn dubare bikin. Di şûna wê de, daneyên zêde di forma qadên "Nasnameya node" û "demjimêr" de li mifteya "P" tê zêdekirin. Bi saya wan, hûn dikarin mifteyek îndeksê ava bikin, ku jê hûn dikarin mifteyek seretayî bistînin, ku, di dawiyê de, hûn dikarin metadata girêk jê bistînin.

Encam

Em encamên pêkanîna LMDB erênî dinirxînin. Piştî wê, hejmara sepanên cemidandinê ji sedî 30 kêm bû.

Di sepanên iOS-ê de şewq û xizaniya databasa key-nirxa LMDB

Encamên xebata ku hatî kirin ji tîmê iOS-ê wêdetir deng veda. Heya niha, yek ji beşên sereke yên "Pel" di serîlêdana Android-ê de jî derbasî karanîna LMDB bûye, û beşên din jî di rê de ne. Zimanê C, ku tê de firoşgeha nirx-kilît tê sepandin, arîkariyek baş bû ku di destpêkê de çarçoveyek serîlêdanê li dora wê-platformê di C++ de biafirîne. Afirînerek kodê hate bikar anîn da ku pirtûkxaneya C++ ya encam bi koda platformê di Objective-C û Kotlin de bêkêmasî girêbide. Djinni ji Dropbox, lê ew çîrokek bi tevahî cûda ye.

Source: www.habr.com

Add a comment