Razdeljevanje na dele
DocStore zapiše eno datoteko na zapis. Brez razdeljevanja bi se vse datoteke velike zbirke nabrale v enem imeniku, operacije nad imenikom pa bi se upočasnile z večanjem števila vnosov. Zato storh datoteke zapisov razporedi v vedra glede na dva znaka ID-ja zapisa:
pages/data/2d/018bcfe5-6800-7000-8000-2d5dba6274da.jsonc
Vedro se določi po začetku zadnje skupine ID-ja UUID (znaka 24 in 25), ki vsebuje naključno entropijo. Dva šestnajstiška znaka pomenita 256 veder, zato ima imenik zbirke s 100k zapisi v povprečju manj kot 400 datotek.
Zakaj rep in ne začetek
ID-ji UUIDv7 se začnejo z 48-bitnim časovnim žigom v milisekundah, zato imajo ID-ji, ustvarjeni v kratkem časovnem razmiku, enake začetne znake. Razdeljevanje po začetku bi vsak val zapisov usmerilo v isti obremenjeni imenik, vedra pa bi se zamenjala šele s časom. Bajti na koncu so za vsak zapis naključni, zato se zapisi od prvega naprej enakomerno porazdelijo.
Razdeljevanje je pri branju in poizvedovanju nevidno: get() izračuna vedro iz ID-ja, stream() pa vrne zapise, razvrščene po ID-ju v vseh vedrih, zato ostranjevanje s kazalcem deluje, kot da bi bila zbirka en sam urejen seznam.
Pri večjem obsegu
Število veder nikoli ne naraste: dva šestnajstiška znaka pomenita 256 imenikov pri kateri koli velikosti zbirke. Raste pa število datotek v posameznem vedru:
| Zapisi | Datotek na vedro |
|---|---|
| 10k | ~40 |
| 100k | ~390 |
| 1M | ~3,900 |
| 10M | ~39,000 |
Sodobni datotečni sistemi indeksirajo vnose v imenik, zato nekaj tisoč datotek na vedro ohranja hitro iskanje posameznih zapisov; 1M zapisov je za get() in indeksirane poizvedbe obvladljivih. Odpiranje shrambe traja enako dolgo ne glede na velikost zbirke: čiščenje osirotelih začasnih datotek se izvede samo, če oznaka mrtvega zapisovalnika pokaže, da se je prejšnji proces med zapisovanjem sesul. Linearno pa rastejo operacije nad celotno zbirko: neindeksirani pregledi, reindex() in verify() obiščejo vsako datoteko z zapisom, zato jih obravnavajte kot paketna opravila. Pri več kot približno 10M zapisih na zbirko postaneta pomembna število datotek v posameznem vedru in skupna poraba inod: zbirke razdelite ali za podatke, namenjene pregledovanju, uporabite segmentirani dnevnik, ki že po zasnovi ohranja majhno število datotek.
Drugi pogoni
SegmentedLog in Queue ne uporabljata razdeljevanja, ker ne ustvarjata ene datoteke na zapis. Dnevnik dodaja zapise v segmentne datoteke pod segments/, omejene z max_segment_bytes (privzeto 1 MiB), čakalna vrsta pa dodaja dogodke v en sam queue.log. Število datotek že po zasnovi ostaja majhno.