
# 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:

```text
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.
