• ClickHouse ने JSON दस्तावेज़ों को string के रूप में डालकर हर बार parse करने वाली bottleneck से बचने के लिए नया JSON type पेश किया है, जो JSON path के अनुसार values को वास्तविक columnar storage में रखता है
  • implementation का core Variant और Dynamic types हैं; एक ही JSON path में integer, string, array जैसे अलग-अलग types आने पर भी इन्हें न्यूनतम common type में जबरन merge नहीं किया जाता
  • max_dynamic_paths की default value 1024 और max_dynamic_types की default value 32 है, जिससे subcolumns और type-specific files की संख्या सीमित कर file descriptors और merge cost में बढ़ोतरी को control किया जाता है
  • type hints, SKIP, SKIP REGEXP से path-specific storage behavior adjust किया जा सकता है, और values को C.a.b जैसी subcolumn syntax से पढ़ा जा सकता है
  • नया type deprecated Object('json') को replace करने के उद्देश्य से बनाया गया है, और JSON key paths को primary key या data-skipping index में इस्तेमाल करने जैसे सुधार भी roadmap में बाकी हैं

JSON को columnar storage के अनुरूप बनाने की चुनौती

  • JSON logs, observability, real-time data streaming, mobile app storage और machine learning pipelines में semi-structured और unstructured data संभालने के लिए common format के रूप में इस्तेमाल होता है
  • ClickHouse एक वास्तविक column-oriented database है, जो tables को disk पर column data files के collection के रूप में store करके compression और vectorized filters/aggregations करता है
  • JSON में भी वही performance पाने के लिए, documents को string column में store करके बाद में parse करने के बजाय हर unique JSON path की value को column की तरह store करना होगा

नया JSON type जिन चार constraints को संभालता है

  • Path-wise columnar storage

    • JSON path-specific values को भी numeric type जैसे सामान्य columns की तरह compress किया जा सके और vectorized तरीके से filter/aggregate किया जा सके
  • Dynamically बदलने वाले types

    • एक ही JSON path a में integer, float, array जैसे अलग-अलग types आ सकते हैं
    • ClickHouse इन्हें पहले से नहीं जान सकता और types एक-दूसरे के compatible न भी हों, इसलिए न्यूनतम common type में मिलाने से information loss हो सकता है
  • Column files की बेतहाशा बढ़ोतरी रोकना

    • हर नए JSON path के लिए नई column file बनाने पर high-cardinality keys वाले data में disk files की संख्या तेजी से बढ़ जाती है
    • file descriptors memory इस्तेमाल करते हैं, और process करने वाली files बढ़ने पर merge performance भी प्रभावित होती है
  • Sparse keys की dense storage

    • जब बहुत-सी unique लेकिन sparse JSON keys हों, तो जिन rows में value नहीं है उनमें बार-बार NULL या default value store नहीं होनी चाहिए
    • PB-scale analytics में scale करने के लिए केवल actual values की dense storage जरूरी है

Variant type: types को जबरन unify न करने की बुनियाद

  • Variant data type JSON से अलग भी इस्तेमाल की जा सकने वाली independent feature है, और एक table column के भीतर अलग-अलग data type values store व read कर सकता है
  • मौजूदा ClickHouse columns का fixed type होता है, और inserted values उसी type की होनी चाहिए या implicitly convert होती हैं
    • Nullable column value file के अलावा NULL mask file इस्तेमाल करता है
    • Array array sizes को अलग file में store करता है और उससे offsets calculate करता है
  • Variant column एक ही concrete type की values को type-specific subcolumns में store करता है
    • उदाहरण: सभी Int64 values C.Int64.bin में, सभी String values C.String.bin में store होती हैं
  • हर row कौन-सा type इस्तेमाल करती है, इसे UInt8 discriminator column से track किया जाता है
    • discriminator value sorted type-name list का index होती है
    • discriminator 255 NULL के लिए reserved value है
    • इसी design के कारण Variant में अधिकतम 255 concrete types हो सकते हैं
  • type-specific data files केवल value वाली rows रखने वाली dense storage structure होती हैं
    • type-specific files में NULL values store नहीं होतीं
    • discriminator row से actual type file में row position खोजने के लिए in-memory UInt64 offset column इस्तेमाल होता है
    • यह offset disk पर store नहीं होता और discriminator column file से on-the-fly generate किया जा सकता है
  • Variant arbitrary nesting support करता है
    • Variant(T1, T2) और Variant(T2, T1) में type order का अर्थ समान है
    • Variant के अंदर फिर Variant रखा जा सकता है
  • किसी specific nested type value को type name को subcolumn की तरह जोड़कर पढ़ा जाता है
    • उदाहरण: C.Int64

Dynamic type: type list पहले से जाने बिना storage

  • Dynamic type Variant पर implemented independent feature है और JSON context के बाहर भी इस्तेमाल हो सकता है
  • Dynamic, Variant में दो features जोड़ता है
    • एक column के भीतर arbitrary type values store करना, बिना type list पहले से specify किए
    • अलग column data files में store होने वाले types की संख्या limit करना
  • internal storage method Variant जैसा ही है, लेकिन C.dynamic_structure.bin file जोड़ी जाती है
    • यह file subcolumn के रूप में stored types की list और type-specific column data file size statistics रखती है
    • यह metadata subcolumn reads और data part merges में इस्तेमाल होता है
  • Dynamic(max_types=N) अलग files में store होने वाले types की संख्या limit करता है
    • 0 <= N < 255
    • default value 32 है
  • limit पर पहुंचने के बाद बाकी type values C.SharedVariant.bin जैसी single column file में store होती हैं
    • इस file का type String है
    • हर row <binary_encoded_data_type><binary_value> structure की string value रखती है
    • कई type values को एक column file में store करके फिर से पढ़ा जा सकता है
  • Dynamic भी Variant की तरह type name को subcolumn के रूप में इस्तेमाल कर specific type value पढ़ सकता है
    • उदाहरण: C.Int64

JSON type declaration और storage structure

  • नया JSON type arbitrary structure वाले JSON objects store करता है और हर JSON value को path-based subcolumn के रूप में पढ़ने देता है
  • type declaration में optional parameters और hints हो सकते हैं
<column_name> JSON(
    max_dynamic_paths=N,
    max_dynamic_types=M,
    some.path TypeName,
    SKIP path.to.skip,
    SKIP REGEXP 'paths_regexp')
  • max_dynamic_paths
    • default value 1024 है
    • अलग subcolumns के रूप में store होने वाले JSON key paths की संख्या specify करता है
    • limit से ऊपर के paths को special structure वाले single subcolumn में साथ store किया जाता है
  • max_dynamic_types
    • default value 32 है
    • value range 0 से 254 तक है
    • एक JSON key path column में अलग column data files के रूप में store होने वाले data types की संख्या specify करता है
    • limit से ऊपर के नए types को special structure वाली single column data file में साथ store किया जाता है
  • some.path TypeName
    • किसी specific JSON path के लिए type hint है
    • वह path हमेशा specified type के subcolumn के रूप में store होता है, जिससे performance guarantee मिलती है
  • SKIP path.to.skip
    • parsing के दौरान specific JSON path को skip करता है
    • वह path JSON column में store नहीं होता
    • अगर specified path nested JSON object है, तो पूरा nested object skip हो जाता है
  • SKIP REGEXP 'path_regexp'
    • regex से match होने वाले paths को JSON parsing के दौरान skip करता है
    • matching paths JSON column में store नहीं होते

JSON paths को columns की तरह पढ़ने का तरीका

  • JSON column के हर unique leaf path की value disk पर दो तरीकों में से एक से store होती है
    • type hint वाले paths सामान्य column data files के रूप में store होते हैं
    • जिन paths के types dynamically बदल सकते हैं, वे Dynamic subcolumn के रूप में store होते हैं
  • JSON type object_structure नाम की special file इस्तेमाल करता है
    • dynamic paths का metadata रखती है
    • हर dynamic path की non-null value statistics रखती है
    • subcolumn reads और data part merges में इस्तेमाल होती है
  • column files की बेतहाशा बढ़ोतरी दो-stage limits से control होती है
    • max_dynamic_types एक JSON key path के भीतर अलग files में store होने वाले types की संख्या limit करता है
    • max_dynamic_paths अलग subcolumns के रूप में store होने वाले JSON key paths की संख्या limit करता है
  • max_dynamic_paths limit से ऊपर के अतिरिक्त dynamic JSON paths shared data के रूप में store होते हैं
    • example files हैं C.object_shared_data.size0.bin, C.object_shared_data.paths.bin, C.object_shared_data.values.bin
    • object_shared_data.values का type String है
    • हर entry में <binary_encoded_data_type><binary_value> structure होता है
  • shared data के लिए भी object_structure.bin में अतिरिक्त statistics store होते हैं
    • वर्तमान shared data column में stored paths में से पहले 10000 paths के लिए non-null value statistics store होते हैं

JSON path syntax और nested objects

  • JSON type हर path की leaf value को path-name-based subcolumn के रूप में पढ़ सकता है
    • उदाहरण: C.a.b
  • जिन paths के लिए type hint specified नहीं है, उनकी value हमेशा Dynamic type रखती है
    • उदाहरण: C.a.d का type Dynamic है
  • Dynamic type के subtype subcolumns special JSON syntax से पढ़े जाते हैं
    • उदाहरण: C.a.d.:Int64
  • nested JSON object को JSON_column.^some.path syntax से JSON type subcolumn की तरह पढ़ा जा सकता है
    • उदाहरण: C.^a
  • मौजूदा dot syntax performance कारणों से nested objects नहीं पढ़ता
    • path-wise literal values पढ़ने में वर्तमान storage structure efficient है
    • path-wise पूरा sub-object पढ़ने के लिए ज्यादा data पढ़ना पड़ता है, इसलिए यह धीमा हो सकता है
    • object return करने के लिए .^ syntax जरूरी है
    • ClickHouse दोनों . syntaxes को unify करने की योजना रखता है

Compact discriminator serialization

  • कई dynamic JSON paths में value type ज्यादातर समान हो सकता है
  • जब unique लेकिन sparse JSON paths बहुत हों, तो हर path की discriminator file में मुख्य रूप से 255, यानी NULL values होती हैं
  • ऐसी files अच्छी तरह compress होती हैं, लेकिन अगर सभी rows की value समान हो तो फिर भी redundancy ज्यादा रहती है
  • ClickHouse ने discriminator serialization के लिए compact format implement किया है
    • सामान्यतः सभी UInt8 discriminator values लिखने के बजाय, अगर target granule के discriminator सभी समान हों तो केवल 3 values serialize की जाती हैं
    • compact granule format indicator
    • उस granule की value count indicator
    • discriminator value
  • यह optimization MergeTree setting use_compact_variant_discriminators_serialization से control होता है
    • default enabled है
    • सामान्य index granularity में 8192 values के बजाय केवल 3 values store होने के case हो सकते हैं

Release status और next steps

  • नया JSON type deprecated Object('json') type को replace करने के लिए design किया गया है
  • implementation ClickHouse 24.08 release में testing के उद्देश्य वाली experimental feature के रूप में उपलब्ध है
  • JSON roadmap में JSON key paths को table primary key या data-skipping index के भीतर इस्तेमाल करने के improvements शामिल हैं
  • Variant और Dynamic जैसे components JSON के अलावा XML, YAML जैसे अतिरिक्त semi-structured types support की बुनियाद बनते हैं
  • ClickHouse Cloud users अगर नया JSON data type test करना चाहते हैं, तो ClickHouse support team से contact करके private preview access request करना होगा

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.