Přejít k obsahu

Dělení do oddílů

DocStore zapisuje jeden soubor pro každý záznam. Bez dělení by se všechny soubory velké kolekce hromadily v jediném adresáři a operace s adresářem by se s rostoucím počtem položek zpomalovaly. storh proto rozděluje soubory záznamů do skupin podle dvou znaků ID záznamu:

Text
pages/data/2d/018bcfe5-6800-7000-8000-2d5dba6274da.jsonc

Skupina se určuje podle začátku UUID poslední části (znaky 24 a 25), která obsahuje náhodnou entropii. Dva hexadecimální znaky dávají 256 skupin, takže kolekce se 100 tisíci záznamy má v průměru méně než 400 souborů v adresáři.

Proč konec, a ne začátek

ID UUIDv7 začínají 48bitovým časovým razítkem v milisekundách, takže ID vytvořená krátce po sobě sdílejí počáteční znaky. Dělení podle předpony by každou dávku zápisů směrovalo do stejného vytíženého adresáře a skupiny by se měnily pouze s postupem času. Koncové bajty jsou pro každý záznam náhodné, takže zápisy se rovnoměrně rozloží hned od prvního záznamu.

Dělení do oddílů je při čtení i dotazování neviditelné: get() vypočítá skupinu z ID a stream() vrací záznamy seřazené podle ID napříč všemi skupinami, takže stránkování pomocí kurzoru funguje, jako by kolekce byla jediným seřazeným seznamem.

Ve velkém měřítku

Počet skupin nikdy neroste: dva hexadecimální znaky znamenají 256 adresářů bez ohledu na velikost kolekce. Roste počet souborů v každé skupině:

Záznamy Souborů ve skupině
10k ~40
100k ~390
1M ~3,900
10M ~39,000

Moderní souborové systémy indexují položky adresářů, takže několik tisíc souborů ve skupině umožňuje rychlé vyhledávání jednotlivých záznamů; milion záznamů zvládají get() a dotazy využívající indexy bez problémů. Otevření úložiště má konstantní čas bez ohledu na velikost kolekce: osiřelé dočasné soubory se prohledávají jen tehdy, když značka po mrtvém zapisovači ukazuje, že předchozí proces havaroval uprostřed zápisu. Lineárně se s rozsahem zvětšují operace nad celou kolekcí: neindexovaná prohledávání, reindex() a verify() procházejí každý soubor záznamu, proto je berte jako dávkové úlohy. Přibližně nad 10 miliony záznamů v kolekci začíná záležet na počtu záznamů ve skupině i na celkovém využití inodů: rozdělte kolekce nebo pro data určená k prohledávání použijte segmentovaný protokol, který už svou konstrukcí udržuje počet souborů nízký.

Ostatní moduly

SegmentedLog a Queue nedělí data do oddílů, protože nevytvářejí jeden soubor pro každý záznam. Protokol přidává data do segmentových souborů v segments/, jejichž velikost je omezena hodnotou max_segment_bytes (výchozí hodnota je 1 MiB), a fronta přidává události do jediného queue.log. Počet souborů tak zůstává nízký už svou konstrukcí.