လက်တွေ့တွင် Spark schemaEvolution

ချစ်လှစွာသောစာဖတ်သူများ၊ မင်္ဂလာရှိသောနေ့ခင်းပါ။

ဤဆောင်းပါးတွင်၊ Neoflex ၏ Big Data Solutions လုပ်ငန်းနယ်ပယ်အတွက် ဦးဆောင်အတိုင်ပင်ခံသည် Apache Spark ကိုအသုံးပြု၍ ပြောင်းလဲနိုင်သောဖွဲ့စည်းပုံစတိုးဆိုင်မျက်နှာစာများတည်ဆောက်ခြင်းအတွက် အသေးစိတ်ရွေးချယ်စရာများကို ဖော်ပြထားပါသည်။

ဒေတာခွဲခြမ်းစိတ်ဖြာမှုပရောဂျက်၏တစ်စိတ်တစ်ပိုင်းအနေဖြင့်၊ လျော့ရဲရဲတင်းတင်းဖွဲ့စည်းထားသောဒေတာကိုအခြေခံ၍ ခင်းကျင်းပြသမှုများတည်ဆောက်ခြင်းတာဝန်သည် မကြာခဏပေါ်ပေါက်ပါသည်။

ပုံမှန်အားဖြင့် ၎င်းတို့သည် JSON သို့မဟုတ် XML ပုံစံဖြင့် သိမ်းဆည်းထားသော စနစ်အမျိုးမျိုးမှ မှတ်တမ်းများ သို့မဟုတ် တုံ့ပြန်မှုများဖြစ်သည်။ ဒေတာကို Hadoop သို့ အပ်လုဒ်လုပ်ပြီး၊ ထို့နောက် ၎င်းမှ စတိုးဆိုင်တစ်ခု တည်ဆောက်ရန် လိုအပ်သည်။ ဥပမာအားဖြင့်၊ Impala မှတဆင့် ဖန်တီးထားသော ဆိုင်မျက်နှာစာသို့ ဝင်ရောက်ခွင့်ကို စုစည်းနိုင်သည်။

ဤကိစ္စတွင်၊ ပစ်မှတ်စတိုးမျက်နှာစာ၏ အပြင်အဆင်ကို ကြိုမသိနိုင်ပါ။ ထို့အပြင်၊ ၎င်းသည်ဒေတာပေါ်တွင်မူတည်သောကြောင့်၊ အစီအစဉ်ကိုကြိုတင်ရေးဆွဲ၍မရသည့်အပြင်၊ ဤဖွဲ့စည်းပုံအလွန်အားနည်းသောဒေတာကိုကျွန်ုပ်တို့ကိုင်တွယ်ဖြေရှင်းနေပါသည်။

ဥပမာ၊ ယနေ့တွင် အောက်ပါတုံ့ပြန်ချက်ကို မှတ်တမ်းတင်ထားသည်-

{source: "app1", error_code: ""}

မနက်ဖြန်တွင် အောက်ပါတုံ့ပြန်မှုသည် တူညီသောစနစ်မှ ထွက်ပေါ်လာသည်-

{source: "app1", error_code: "error", description: "Network error"}

ရလဒ်အနေဖြင့်၊ အခြားအကွက်ကို စတိုးမျက်နှာစာ - ဖော်ပြချက်သို့ ပေါင်းထည့်သင့်ပြီး ၎င်းသည် လာမည်၊ မလာမည်ကို မည်သူမျှ မသိနိုင်ပါ။

ထိုကဲ့သို့သောဒေတာများတွင် mart တစ်ခုဖန်တီးခြင်း၏တာဝန်သည် စံနမူနာရှိပြီး Spark တွင် ၎င်းအတွက်ကိရိယာများစွာရှိသည်။ အရင်းအမြစ်ဒေတာကိုခွဲခြမ်းစိတ်ဖြာရန်အတွက်၊ JSON နှင့် XML နှစ်ခုစလုံးအတွက် ပံ့ပိုးမှုရှိပြီး ယခင်ကမသိရသေးသော schema အတွက် schemaEvolution ပံ့ပိုးမှုကို ပေးထားသည်။

ပထမတစ်ချက်မှာ ဖြေရှင်းချက်က ရိုးရှင်းပါတယ်။ JSON ဖြင့် ဖိုင်တွဲကို ယူ၍ ဒေတာဘောင်သို့ ဖတ်ရန် လိုအပ်သည်။ Spark သည် schema တစ်ခုကို ဖန်တီးပြီး nested data ကို တည်ဆောက်ပုံများအဖြစ် ပြောင်းလဲပေးပါမည်။ ထို့နောက်၊ Hive metastore တွင် စတိုးဆိုင်မျက်နှာစာတွင် စာရင်းသွင်းခြင်းဖြင့် Impala တွင် ပံ့ပိုးထားသည့်အရာအားလုံးကို ပါကေးဖြင့်သိမ်းဆည်းရန်လိုအပ်ပါသည်။

အရာအားလုံးရိုးရှင်းပုံရသည်။

သို့ရာတွင်၊ စာရွက်စာတမ်းရှိ ဥပမာတိုများဖြင့် လက်တွေ့တွင် ပြဿနာများစွာနှင့် ဘာလုပ်ရမည်ကို မရှင်းလင်းပါ။

စာရွက်စာတမ်းသည် စတိုးဆိုင်မျက်နှာစာ ဖန်တီးခြင်းအတွက်မဟုတ်ဘဲ JSON သို့မဟုတ် XML ကို ဒေတာဘောင်တစ်ခုသို့ ဖတ်ခြင်းအတွက် ချဉ်းကပ်ပုံကို ဖော်ပြသည်။

ပြောရရင်၊ JSON ကို ဘယ်လိုဖတ်ပြီး ခွဲခြမ်းစိတ်ဖြာရမလဲဆိုတာ ရိုးရှင်းစွာပြထားပါတယ်-

df = spark.read.json(path...)

၎င်းသည် Spark တွင် ဒေတာရရှိနိုင်စေရန် လုံလောက်ပါသည်။

လက်တွေ့တွင်၊ ဖိုဒါတစ်ခုမှ JSON ဖိုင်များကို ဖတ်ရှုပြီး ဒေတာဘောင်တစ်ခု ဖန်တီးရုံထက် ပိုမိုရှုပ်ထွေးပါသည်။ အခြေအနေသည် ဤကဲ့သို့ ဖြစ်သည်- အချို့သော ပြပွဲတစ်ခုရှိနေပြီ၊ ဒေတာအသစ်များ နေ့စဉ်ရောက်ရှိလာသည်၊ ၎င်းတို့ကို ပြပွဲတွင် ထည့်သွင်းရန် လိုအပ်သည်၊ အစီအစဉ်မှာ ကွဲပြားနိုင်သည်ကို မမေ့မလျော့ဘဲ ရှိနေသည်။

ဆိုင်မျက်နှာစာ ဆောက်လုပ်ရန်အတွက် ပုံမှန်အစီအစဉ်မှာ အောက်ပါအတိုင်းဖြစ်သည်။

1 အဆင့်။ ဒေတာကို Hadoop တွင် တင်ဆောင်ပြီး နောက်တွင် နေ့စဉ် ထပ်လောင်းတင်ပေးပြီး partition အသစ်တစ်ခုသို့ ပေါင်းထည့်သည်။ ရလဒ်သည် နေ့အလိုက် ပိုင်းခြားထားသော အရင်းအမြစ်ဒေတာပါသည့် ဖိုင်တွဲတစ်ခုဖြစ်သည်။

2 အဆင့်။ ကနဦးစတင်နေစဉ်တွင်၊ ဤဖိုင်တွဲကို Spark သုံးပြီး ဖတ်ပြီး ခွဲခြမ်းစိတ်ဖြာပါသည်။ ရလဒ်ဒေတာဘောင်ကို Impala ထဲသို့ ထည့်သွင်းနိုင်သည့် ဥပမာအားဖြင့် ပါကေးဖြင့် ခွဲခြမ်းစိတ်ဖြာနိုင်သော ဖော်မတ်ဖြင့် သိမ်းဆည်းထားသည်။ ၎င်းသည် ဤအချက်အထိ စုဆောင်းထားသည့် ဒေတာအားလုံးနှင့်အတူ ပစ်မှတ်စတိုးဆိုင်ကို ဖန်တီးပေးသည်။

3 အဆင့်။ စတိုးဆိုင်မျက်နှာစာကို နေ့စဉ် အပ်ဒိတ်လုပ်မည့် ဒေါင်းလုဒ်တစ်ခု ဖန်တီးထားသည်။
တိုးမြှင်တင်ခြင်းဆိုင်ရာ မေးခွန်း၊ စတိုးမျက်နှာစာကို ပိုင်းခြားရန် လိုအပ်ခြင်းနှင့် စတိုးမျက်နှာစာ၏ ယေဘူယျ အပြင်အဆင်ကို ပံ့ပိုးပေးရန် မေးခွန်းများ ပေါ်ပေါက်လာသည်။

ဥပမာတစ်ခုပေးကြည့်ရအောင်။ repository တစ်ခုတည်ဆောက်ခြင်း၏ ပထမအဆင့်ကို အကောင်အထည် ဖော်ခဲ့ပြီး၊ ဖိုင်တွဲတစ်ခုသို့ JSON ဖိုင်များ အပ်လုဒ်တင်ခြင်းကို စီစဉ်သတ်မှတ်ထားပါသည်။

၎င်းတို့ထံမှ ဒေတာဘောင်တစ်ခုကို ဖန်တီးပြီးနောက် ၎င်းတို့ကို ပြပွဲတစ်ခုအဖြစ် သိမ်းဆည်းရန် ပြဿနာမရှိပါ။ ဒါက Spark documentation မှာ အလွယ်တကူ ရှာတွေ့နိုင်တဲ့ ပထမဆုံးအဆင့်ပါ။

df = spark.read.option("mergeSchema", True).json(".../*") 
df.printSchema()

root 
|-- a: long (nullable = true) 
|-- b: string (nullable = true) 
|-- c: struct (nullable = true) |    
|-- d: long (nullable = true)

အားလုံးအဆင်ပြေပုံရပါတယ်။

ကျွန်ုပ်တို့သည် JSON ကိုဖတ်ပြီး ခွဲခြမ်းစိပ်ဖြာပြီးသောအခါ၊ ကျွန်ုပ်တို့သည် ဒေတာဘောင်ကို ပါကေးအဖြစ်သိမ်းဆည်းကာ အဆင်ပြေသည့်နည်းလမ်းဖြင့် Hive တွင် စာရင်းသွင်းပါ-

df.write.format(“parquet”).option('path','<External Table Path>').saveAsTable('<Table Name>')

ခင်းကျင်းပြသမှုတစ်ခုရရှိသည်။

သို့သော် နောက်တစ်နေ့တွင် အရင်းအမြစ်မှ ဒေတာအသစ် ထပ်ထည့်ခဲ့သည်။ ကျွန်ုပ်တို့တွင် JSON ပါသည့် ဖိုင်တွဲတစ်ခုရှိပြီး ဤဖိုင်တွဲကို အခြေခံ၍ ဖန်တီးထားသော စတိုးဆိုင်တစ်ခုရှိသည်။ အရင်းအမြစ်မှ ဒေတာ၏ နောက်အပိုင်းကို တင်ပြီးနောက်၊ စတိုးမျက်နှာစာတွင် တစ်ရက်အတွက် လုံလောက်သောဒေတာမရှိပါ။

ယုတ္တိတန်သောဖြေရှင်းချက်မှာ စတိုးဆိုင်မျက်နှာစာအား နေ့စဥ်အပိုင်းပိုင်းခွဲခြင်းဖြစ်ပြီး နောက်နေ့တွင် အပိုင်းအသစ်တစ်ခု ထပ်ထည့်နိုင်စေမည်ဖြစ်သည်။ ၎င်းအတွက် ယန္တရားကိုလည်း လူသိများသည်၊ Spark သည် သင့်အား partitions များကို သီးခြားစီမှတ်တမ်းတင်ရန် ခွင့်ပြုသည်။

ပထမဦးစွာ ကျွန်ုပ်တို့သည် အထက်ဖော်ပြပါအတိုင်း ဒေတာကို အပိုင်းပိုင်းခွဲခြင်းသာ ပေါင်းထည့်ကာ ကနဦး loading ကို လုပ်ဆောင်ပါသည်။ ဤလုပ်ဆောင်ချက်ကို စတိုးမျက်နှာစာ ကနဦးသတ်မှတ်ခြင်းဟုခေါ်ပြီး တစ်ကြိမ်သာ လုပ်ဆောင်သည်-

df.write.partitionBy("date_load").mode("overwrite").parquet(dbpath + "/" + db + "/" + destTable)

နောက်နေ့တွင် partition အသစ်ကိုသာ ဒေါင်းလုဒ်လုပ်ပါ။

df.coalesce(1).write.mode("overwrite").parquet(dbpath + "/" + db + "/" + destTable +"/date_load=" + date_load + "/")

ကျန်ရှိနေသေးသည်မှာ schema ကိုမွမ်းမံရန်အတွက် Hive တွင်ပြန်လည်မှတ်ပုံတင်ရန်ဖြစ်သည်။
သို့သော် ဤနေရာတွင် ပြဿနာများ ပေါ်လာသည်။

ပထမပြဿနာ။ မကြာမီ သို့မဟုတ် နောက်ပိုင်းတွင် ရရှိလာသော ပါကေးကို ဖတ်၍မရတော့ပါ။ ပါကေးနှင့် JSON သည် အကွက်လပ်များကို ကွဲပြားစွာ ဆက်ဆံပုံကြောင့်ဖြစ်သည်။

ပုံမှန်အခြေအနေတစ်ခုကို သုံးသပ်ကြည့်ရအောင်။ ဥပမာ၊ မနေ့က JSON ရောက်လာသည်-

День 1: {"a": {"b": 1}},

ယနေ့တွင် အလားတူ JSON သည် ဤကဲ့သို့ ဖြစ်သည်-

День 2: {"a": null}

ကျွန်ုပ်တို့တွင် မတူညီသော partition နှစ်ခုရှိသည်၊ တစ်ခုစီတွင် လိုင်းတစ်ခုရှိသည် ဆိုကြပါစို့။
အရင်းအမြစ်ဒေတာတစ်ခုလုံးကို ကျွန်ုပ်တို့ဖတ်ရှုသည့်အခါ Spark သည် အမျိုးအစားကို ဆုံးဖြတ်နိုင်မည်ဖြစ်ပြီး “a” သည် အမျိုးအစား INT ၏ အစုအဝေးအကွက် “b” ဖြင့် အမျိုးအစား “ဖွဲ့စည်းပုံ” နယ်ပယ်တစ်ခုဖြစ်ကြောင်း နားလည်လာမည်ဖြစ်သည်။ သို့သော်၊ အခန်းကန့်တစ်ခုစီကို သီးခြားစီသိမ်းဆည်းထားပါက၊ ရလဒ်မှာ သဟဇာတမဖြစ်သော အပိုင်းအစီအစဉ်များဖြင့် ပါကေးတစ်ခုဖြစ်သည်။

df1 (a: <struct<"b": INT>>)
df2 (a: STRING NULLABLE)

ဤအခြေအနေကို ကောင်းစွာသိသောကြောင့် အရင်းအမြစ်ဒေတာကို ခွဲခြမ်းစိတ်ဖြာသည့်အခါ ဗလာအကွက်များကို ဖယ်ရှားရန် ရွေးချယ်မှုတစ်ခုကို အထူးထည့်သွင်းထားသည်-

df = spark.read.json("...", dropFieldIfAllNull=True)

ဤကိစ္စတွင်၊ ပါကေးသည်အတူတကွဖတ်ရှုနိုင်သောအပိုင်းများပါ ၀ င်လိမ့်မည်။
ဒါကို လက်တွေ့လုပ်တဲ့သူတွေက ရှိုက်ကြီးတငင် ပြုံးကြလိမ့်မယ်။ အဘယ်ကြောင့်? ဟုတ်တယ်၊ ဘာကြောင့်လဲဆိုတော့ နောက်ထပ် အခြေအနေ နှစ်ခု ထပ်ဖြစ်လာနိုင်လို့ပါ။ သို့မဟုတ် သုံးခု။ သို့မဟုတ် လေးခု။ ပထမအချက်မှာ သေချာလုနီးပါးဖြစ်သည့် ဂဏန်းအမျိုးအစားများသည် မတူညီသော JSON ဖိုင်များတွင် ကွဲပြားနေမည် ဖြစ်သည်။ ဥပမာ၊ {intField: 1} နှင့် {intField: 1.1}။ ထိုသို့သောအကွက်များသည် တစ်သုတ်တွင် ပေါ်လာပါက၊ schema ပေါင်းစည်းမှုသည် အရာအားလုံးကို မှန်ကန်စွာဖတ်နိုင်ပြီး အတိကျဆုံးအမျိုးအစားသို့ ဦးတည်သွားမည်ဖြစ်သည်။ ဒါပေမယ့် မတူဘူးဆိုရင် တစ်ခုက intField: int ရှိမယ်၊ နောက်တစ်ခုက intField: နှစ်ဆရှိမယ်။

ဤအခြေအနေကို ကိုင်တွယ်ရန် အောက်ပါအလံ ရှိပါသည်။

df = spark.read.json("...", dropFieldIfAllNull=True, primitivesAsString=True)

ယခု ကျွန်ုပ်တို့တွင် အခန်းကန့်များတည်ရှိရာ ဖိုင်တွဲတစ်ခုရှိပြီး၊ ဒေတာဘောင်တစ်ခုတည်းနှင့် စတိုးဆိုင်မျက်နှာစာတစ်ခုလုံး၏ တရားဝင်ပါကေးတစ်ခုအဖြစ် ဖတ်နိုင်သည်။ ဟုတ်လား? မရှိ

ကျွန်ုပ်တို့သည် Hive တွင် ဇယားကို စာရင်းသွင်းထားကြောင်း သတိရရပါမည်။ Hive သည် အကွက်အမည်များတွင် အသေးအဖွဲမဟုတ်သော်လည်း ပါကေးဖြစ်သည်။ ထို့ကြောင့်၊ schemas ပါရှိသော partitions များသည် field1: int နှင့် Field1: int တို့သည် Hive အတွက်တူညီသော်လည်း Spark အတွက်မဟုတ်ပါ။ အကွက်အမည်များကို စာလုံးအသေးသို့ ပြောင်းရန် မမေ့ပါနှင့်။

ဒီနောက်မှာတော့ အားလုံးအဆင်ပြေသွားပုံရပါတယ်။

သို့သော်၊ ဤမျှလောက်မရိုးရှင်းပါ။ ဒုတိယ၊ လူသိများသောပြဿနာတစ်ခုပေါ်လာသည်။ အပိုင်းအသစ်တစ်ခုစီကို သီးခြားစီသိမ်းဆည်းထားသောကြောင့် အခန်းကန့်ဖိုင်တွဲတွင် Spark ဝန်ဆောင်မှုဖိုင်များ ဥပမာ၊ _SUCCESS လုပ်ဆောင်ချက် အောင်မြင်မှုအလံပါရှိသည်။ ၎င်းသည် ပါကေးခင်းရန် ကြိုးပမ်းသောအခါ အမှားအယွင်း ဖြစ်ပေါ်လာလိမ့်မည်။ ၎င်းကိုရှောင်ရှားရန် Spark ဖိုဒါသို့ဝန်ဆောင်မှုဖိုင်များထည့်ခြင်းမှတားဆီးခြင်းဖြင့် configuration ကို configure လုပ်ရန်လိုအပ်သည်-

hadoopConf = sc._jsc.hadoopConfiguration()
hadoopConf.set("parquet.enable.summary-metadata", "false")
hadoopConf.set("mapreduce.fileoutputcommitter.marksuccessfuljobs", "false")

ယခု နေ့တိုင်း parquet partition အသစ်တစ်ခုသည် နေ့စဥ်ခွဲခြမ်းစိတ်ဖြာထားသောဒေတာတည်ရှိရာ ပစ်မှတ်စတိုးမျက်နှာစာဖိုဒါသို့ နေ့တိုင်းထည့်နေပုံရသည်။ ဒေတာအမျိုးအစားကွဲလွဲမှုများရှိသည့် အပိုင်းခွဲများမရှိစေရန်အတွက် ကျွန်ုပ်တို့ ကြိုတင်ဂရုစိုက်ထားပါသည်။

ဒါပေမယ့် တတိယပြဿနာနဲ့ ရင်ဆိုင်နေရတယ်။ ယခုအခါတွင် ယေဘုယျ schema ကို မသိရသည့်အပြင်၊ Hive တွင် ဇယားကွက်အသစ်တစ်ခုစီသည် ပုံပျက်သွားဖွယ်အရှိဆုံး schema တွင် ပုံပျက်နေနိုင်သောကြောင့် ဇယားတွင် မှားယွင်းသော schema ရှိနေပါသည်။

ဇယားကို ပြန်လည်မှတ်ပုံတင်ရန် လိုအပ်သည်။ ၎င်းကိုရိုးရှင်းစွာလုပ်ဆောင်နိုင်သည်- စတိုးဆိုင်မျက်နှာစာ၏ပါကေးကိုထပ်မံဖတ်ရှုပါ၊ schema ကိုယူ၍ ၎င်းအပေါ်အခြေခံ၍ DDL တစ်ခုဖန်တီးပါ၊ ၎င်းသည် Hive တွင် folder ကိုပြင်ပဇယားအဖြစ်ပြန်လည်မှတ်ပုံတင်နိုင်ပြီး၊ ပစ်မှတ်စတိုးမျက်နှာစာ၏ schema ကိုမွမ်းမံခြင်း။

စတုတ္ထပြဿနာကို ကျွန်ုပ်တို့ ရင်ဆိုင်ရသည်။ ဇယားကို ပထမအကြိမ် စာရင်းသွင်းတုန်းက Spark ကို အားကိုးတယ်။ ယခုကျွန်ုပ်တို့ကိုယ်တိုင်ပြုလုပ်ပြီးပါကေးကွက်လပ်များသည် Hive မှခွင့်မပြုသောစာလုံးများဖြင့်အစပြုနိုင်ကြောင်းသတိရရန်လိုအပ်သည်။ ဥပမာအားဖြင့်၊ Spark သည် “corrupt_record” အကွက်တွင် ခွဲခြမ်းစိတ်ဖြာ၍မရသော လိုင်းများကို ထုတ်လွှတ်သည်။ ထိုသို့သောအကွက်သည် မလွတ်မြောက်ဘဲ Hive တွင် စာရင်းသွင်း၍မရပါ။

ဒါကိုသိရင် diagram ကိုရနိုင်တယ်၊

f_def = ""
for f in pf.dtypes:
  if f[0] != "date_load":
    f_def = f_def + "," + f[0].replace("_corrupt_record", "`_corrupt_record`") + " " + f[1].replace(":", "`:").replace("<", "<`").replace(",", ",`").replace("array<`", "array<") 
table_define = "CREATE EXTERNAL TABLE jsonevolvtable (" + f_def[1:] + " ) "
table_define = table_define + "PARTITIONED BY (date_load string) STORED AS PARQUET LOCATION '/user/admin/testJson/testSchemaEvolution/pq/'"
hc.sql("drop table if exists jsonevolvtable")
hc.sql(table_define)

ကုဒ် ("_corrupt_record", "`_corrupt_record`") + "" + f[1].replace(":", "`:").replace("<","<`").replace(",", ",`").အစားထိုး("array<`","array<") DDL ကို ဘေးကင်းစေသည်၊ ဆိုလိုသည်မှာ၊ အစား၊

create table tname (_field1 string, 1field string)

“_field1၊ 1field” ကဲ့သို့သော အကွက်အမည်များဖြင့်၊ အကွက်အမည်များကို လွတ်ကင်းသည့်နေရာတွင် လုံခြုံသော DDL တစ်ခုကို ပြုလုပ်သည်- ဇယား `tname` (`_field1` စာကြောင်း၊ `1field` စာကြောင်း) ကို ဖန်တီးပါ။

မေးခွန်းပေါ်လာသည်- ပြီးပြည့်စုံသော schema (pf ကုဒ်တွင်) ဖြင့် dataframe ကိုမည်သို့မှန်ကန်စွာရနိုင်မည်နည်း။ ဒီ pf ကိုဘယ်လိုရနိုင်မလဲ။ ဒါက ပဉ္စမပြဿနာပါ။ ပစ်မှတ်စတိုးမျက်နှာစာ၏ ပါကေးဖိုင်များပါသည့် ဖိုင်တွဲမှ အခန်းကန့်အားလုံး၏ ပုံကြမ်းကို ပြန်ဖတ်မလား။ ဒီနည်းလမ်းက အလုံခြုံဆုံးဖြစ်ပေမယ့် ခက်ခဲပါတယ်။

အစီအစဉ်သည် Hive တွင် ရှိနှင့်ပြီးဖြစ်သည်။ ဇယားတစ်ခုလုံး၏ schema နှင့် partition အသစ်ကို ပေါင်းစပ်ခြင်းဖြင့် schema အသစ်တစ်ခုကို သင်ရနိုင်သည်။ ဆိုလိုသည်မှာ သင်သည် Hive မှ table schema ကိုယူ၍ partition အသစ်၏ schema နှင့်ပေါင်းစပ်ရန်လိုအပ်သည်ဟု ဆိုလိုသည်။ Hive မှ စမ်းသပ်မှု မက်တာဒေတာကို ဖတ်ခြင်း၊ ၎င်းကို ယာယီဖိုင်တွဲတစ်ခုတွင် သိမ်းဆည်းကာ Spark ကို အသုံးပြု၍ အခန်းကန့်နှစ်ခုလုံးကို တစ်ပြိုင်နက်ဖတ်ခြင်းဖြင့် ၎င်းကို လုပ်ဆောင်နိုင်သည်။

အခြေခံအားဖြင့်၊ သင်လိုအပ်သောအရာအားလုံးရှိသည်- Hive ရှိမူရင်းဇယားပုံစံနှင့် အခန်းကန့်အသစ်။ ငါတို့မှာလည်း ဒေတာရှိတယ်။ ကျန်ရှိနေသေးသည်မှာ စတိုးဆိုင်မျက်နှာစာပုံစံနှင့် ကွက်လပ်အသစ်များကို ဖန်တီးထားသော အပိုင်းခွဲမှ ပေါင်းစပ်ထားသော စကေးအသစ်ကို ရယူရန်ဖြစ်သည်။

from pyspark.sql import HiveContext
from pyspark.sql.functions import lit
hc = HiveContext(spark)
df = spark.read.json("...", dropFieldIfAllNull=True)
df.write.mode("overwrite").parquet(".../date_load=12-12-2019")
pe = hc.sql("select * from jsonevolvtable limit 1")
pe.write.mode("overwrite").parquet(".../fakePartiton/")
pf = spark.read.option("mergeSchema", True).parquet(".../date_load=12-12-2019/*", ".../fakePartiton/*")

ထို့နောက်၊ ကျွန်ုပ်တို့သည် ယခင်အပိုင်းအစအတိုင်း ဇယားမှတ်ပုံတင်ခြင်း DDL ကို ဖန်တီးသည်။
ကွင်းဆက်တစ်ခုလုံး မှန်ကန်စွာ အလုပ်လုပ်ပါက၊ ပြောရရင်၊ ကနဦး ဝန်တစ်ခု ရှိခဲ့ပြီး၊ ဇယားကို Hive တွင် မှန်ကန်စွာ ဖန်တီးခဲ့ပါက၊ ကျွန်ုပ်တို့သည် မွမ်းမံထားသော ဇယားပုံစံတစ်ခုကို ရရှိပါမည်။

နောက်ဆုံးပြဿနာမှာ Hive table တွင် partition တစ်ခုကို အလွယ်တကူ ထည့်၍မရသောကြောင့်၊ ၎င်း၏ partition တည်ဆောက်ပုံကို ပြင်ဆင်ရန် Hive ကို တွန်းအားပေးရန် လိုအပ်သည်-

from pyspark.sql import HiveContext
hc = HiveContext(spark) 
hc.sql("MSCK REPAIR TABLE " + db + "." + destTable)

JSON ကိုဖတ်ခြင်းနှင့် ၎င်းကိုအခြေခံ၍ စတိုးဆိုင်မျက်နှာစာဖန်တီးခြင်း၏ရိုးရှင်းသောအလုပ်သည် သီးခြားစီရှာဖွေရမည့်ဖြေရှင်းနည်းများဖြစ်ပြီး သွယ်ဝိုက်သောအခက်အခဲများစွာကို ကျော်လွှားနိုင်သည်။ ဤဖြေရှင်းနည်းများသည် ရိုးရှင်းသော်လည်း ၎င်းတို့ကိုရှာဖွေရန် အချိန်များစွာလိုအပ်ပါသည်။

အရောင်းပြခန်း ဆောက်လုပ်မှုကို အကောင်အထည်ဖော်ရန်၊

  • ဝန်ဆောင်မှုဖိုင်များကို ဖယ်ရှားရန် စတိုးဆိုင်မျက်နှာစာသို့ အခန်းကန့်များထည့်ပါ။
  • Spark ရိုက်ထည့်လိုက်သော အရင်းအမြစ်ဒေတာရှိ အကွက်အလွတ်များကို ကိုင်တွယ်ဖြေရှင်းပါ။
  • ရိုးရှင်းသောအမျိုးအစားများကို string သို့ ကာစ်ပါ။
  • အကွက်အမည်များကို စာလုံးသေးအဖြစ် ပြောင်းပါ။
  • Hive တွင် သီးခြားဒေတာအပ်လုဒ်နှင့် ဇယားမှတ်ပုံတင်ခြင်း (DDL ဖန်တီးမှု)
  • Hive နှင့် တွဲဖက်၍မရသော အကွက်အမည်များကို ရှောင်ရန် မမေ့ပါနှင့်
  • Hive တွင် ဇယားမှတ်ပုံတင်ခြင်းကို အပ်ဒိတ်လုပ်ရန် လေ့လာပါ။

အကျဉ်းချုပ်ပြောရလျှင် စတိုးဆိုင်မျက်နှာစာများ တည်ဆောက်ရန် ဆုံးဖြတ်ချက်သည် ချို့ယွင်းချက်များစွာဖြင့် ပြည့်နှက်နေပါသည်။ ထို့ကြောင့် အကောင်အထည်ဖော်ရာတွင် အခက်အခဲများ ကြုံလာပါက အောင်မြင်သော ကျွမ်းကျင်မှုရှိသော အတွေ့အကြုံရှိသော လုပ်ဖော်ကိုင်ဖက်ထံ လှည့်ခြင်းသည် ပိုကောင်းပါသည်။

ဤဆောင်းပါးကိုဖတ်ရှုခြင်းအတွက်ကျေးဇူးတင်ပါသည်၊ ကျွန်ုပ်တို့သည်သင့်အတွက်အသုံးဝင်သောအချက်အလက်များကိုရှာဖွေတွေ့ရှိရန်မျှော်လင့်ပါသည်။

source: www.habr.com

မှတ်ချက် Add