ಆಚರಣೆಯಲ್ಲಿ ಸ್ಕೀಮಾವಿಕಸನವನ್ನು ಸ್ಪಾರ್ಕ್ ಮಾಡಿ

ಆತ್ಮೀಯ ಓದುಗರೇ, ಶುಭ ದಿನ!

ಈ ಲೇಖನದಲ್ಲಿ, ನಿಯೋಫ್ಲೆಕ್ಸ್‌ನ ಬಿಗ್ ಡೇಟಾ ಸೊಲ್ಯೂಷನ್ಸ್ ವ್ಯವಹಾರ ಪ್ರದೇಶದ ಪ್ರಮುಖ ಸಲಹೆಗಾರರು ಅಪಾಚೆ ಸ್ಪಾರ್ಕ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ವೇರಿಯಬಲ್ ಸ್ಟ್ರಕ್ಚರ್ ಶೋಕೇಸ್‌ಗಳನ್ನು ನಿರ್ಮಿಸುವ ಆಯ್ಕೆಗಳನ್ನು ವಿವರವಾಗಿ ವಿವರಿಸುತ್ತಾರೆ.

ಡೇಟಾ ವಿಶ್ಲೇಷಣೆ ಯೋಜನೆಯ ಭಾಗವಾಗಿ, ಸಡಿಲವಾಗಿ ರಚನಾತ್ಮಕ ಡೇಟಾವನ್ನು ಆಧರಿಸಿ ಅಂಗಡಿ ಮುಂಭಾಗಗಳನ್ನು ನಿರ್ಮಿಸುವ ಕಾರ್ಯವು ಹೆಚ್ಚಾಗಿ ಉದ್ಭವಿಸುತ್ತದೆ.

ಸಾಮಾನ್ಯವಾಗಿ ಇವುಗಳು ಲಾಗ್‌ಗಳು ಅಥವಾ ವಿವಿಧ ಸಿಸ್ಟಮ್‌ಗಳಿಂದ ಪ್ರತಿಕ್ರಿಯೆಗಳು, JSON ಅಥವಾ XML ಆಗಿ ಉಳಿಸಲಾಗಿದೆ. ಡೇಟಾವನ್ನು Hadoop ಗೆ ಅಪ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ, ನಂತರ ನೀವು ಅವರಿಂದ ಅಂಗಡಿ ಮುಂಭಾಗವನ್ನು ನಿರ್ಮಿಸಬೇಕಾಗುತ್ತದೆ. ನಾವು ರಚಿಸಿದ ಪ್ರದರ್ಶನಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಆಯೋಜಿಸಬಹುದು, ಉದಾಹರಣೆಗೆ, ಇಂಪಾಲಾ ಮೂಲಕ.

ಈ ಸಂದರ್ಭದಲ್ಲಿ, ಗುರಿ ಅಂಗಡಿಯ ಮುಂಭಾಗದ ಸ್ಕೀಮಾ ಮೊದಲೇ ತಿಳಿದಿಲ್ಲ. ಇದಲ್ಲದೆ, ಯೋಜನೆಯನ್ನು ಮುಂಚಿತವಾಗಿ ರಚಿಸಲಾಗುವುದಿಲ್ಲ, ಏಕೆಂದರೆ ಇದು ಡೇಟಾವನ್ನು ಅವಲಂಬಿಸಿರುತ್ತದೆ ಮತ್ತು ನಾವು ಈ ಸಡಿಲವಾಗಿ ರಚನಾತ್ಮಕ ಡೇಟಾದೊಂದಿಗೆ ವ್ಯವಹರಿಸುತ್ತಿದ್ದೇವೆ.

ಉದಾಹರಣೆಗೆ, ಇಂದು ಕೆಳಗಿನ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಲಾಗ್ ಮಾಡಲಾಗಿದೆ:

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

ಮತ್ತು ನಾಳೆ ಅದೇ ವ್ಯವಸ್ಥೆಯಿಂದ ಈ ಕೆಳಗಿನ ಉತ್ತರ ಬರುತ್ತದೆ:

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

ಪರಿಣಾಮವಾಗಿ, ಶೋಕೇಸ್‌ಗೆ ಇನ್ನೂ ಒಂದು ಕ್ಷೇತ್ರವನ್ನು ಸೇರಿಸಬೇಕು - ವಿವರಣೆ, ಮತ್ತು ಅದು ಬರುತ್ತದೋ ಇಲ್ಲವೋ ಎಂಬುದು ಯಾರಿಗೂ ತಿಳಿದಿಲ್ಲ.

ಅಂತಹ ಡೇಟಾದಲ್ಲಿ ಅಂಗಡಿಯ ಮುಂಭಾಗವನ್ನು ರಚಿಸುವ ಕಾರ್ಯವು ಸಾಕಷ್ಟು ಪ್ರಮಾಣಿತವಾಗಿದೆ ಮತ್ತು ಸ್ಪಾರ್ಕ್ ಇದಕ್ಕಾಗಿ ಹಲವಾರು ಸಾಧನಗಳನ್ನು ಹೊಂದಿದೆ. ಮೂಲ ಡೇಟಾವನ್ನು ಪಾರ್ಸಿಂಗ್ ಮಾಡಲು, JSON ಮತ್ತು XML ಎರಡಕ್ಕೂ ಬೆಂಬಲವಿದೆ ಮತ್ತು ಹಿಂದೆ ತಿಳಿದಿಲ್ಲದ ಸ್ಕೀಮಾಗೆ, ಸ್ಕೀಮಾ ಎವಲ್ಯೂಷನ್‌ಗೆ ಬೆಂಬಲವನ್ನು ಒದಗಿಸಲಾಗಿದೆ.

ಮೊದಲ ನೋಟದಲ್ಲಿ, ಪರಿಹಾರವು ಸರಳವಾಗಿ ಕಾಣುತ್ತದೆ. ನೀವು JSON ಜೊತೆಗೆ ಫೋಲ್ಡರ್ ಅನ್ನು ತೆಗೆದುಕೊಂಡು ಅದನ್ನು ಡೇಟಾಫ್ರೇಮ್‌ಗೆ ಓದಬೇಕು. ಸ್ಪಾರ್ಕ್ ಸ್ಕೀಮಾವನ್ನು ರಚಿಸುತ್ತದೆ, ನೆಸ್ಟೆಡ್ ಡೇಟಾವನ್ನು ರಚನೆಗಳಾಗಿ ಪರಿವರ್ತಿಸುತ್ತದೆ. ಇದಲ್ಲದೆ, ಹೈವ್ ಮೆಟಾಸ್ಟೋರ್‌ನಲ್ಲಿ ಸ್ಟೋರ್‌ಫ್ರಂಟ್ ಅನ್ನು ನೋಂದಾಯಿಸುವ ಮೂಲಕ ಇಂಪಾಲಾದಲ್ಲಿ ಸಹ ಬೆಂಬಲಿಸುವ ಪ್ಯಾರ್ಕ್ವೆಟ್‌ನಲ್ಲಿ ಎಲ್ಲವನ್ನೂ ಉಳಿಸಬೇಕಾಗಿದೆ.

ಎಲ್ಲವೂ ಸರಳವಾಗಿದೆ ಎಂದು ತೋರುತ್ತದೆ.

ಆದಾಗ್ಯೂ, ಪ್ರಾಯೋಗಿಕವಾಗಿ ಹಲವಾರು ಸಮಸ್ಯೆಗಳೊಂದಿಗೆ ಏನು ಮಾಡಬೇಕೆಂದು ದಸ್ತಾವೇಜನ್ನು ಚಿಕ್ಕ ಉದಾಹರಣೆಗಳಿಂದ ಸ್ಪಷ್ಟವಾಗಿಲ್ಲ.

ದಸ್ತಾವೇಜನ್ನು ಅಂಗಡಿಯ ಮುಂಭಾಗವನ್ನು ರಚಿಸದೆ ಇರುವ ವಿಧಾನವನ್ನು ವಿವರಿಸುತ್ತದೆ, ಆದರೆ JSON ಅಥವಾ XML ಅನ್ನು ಡೇಟಾಫ್ರೇಮ್‌ಗೆ ಓದುತ್ತದೆ.

ಅವುಗಳೆಂದರೆ, ಇದು JSON ಅನ್ನು ಹೇಗೆ ಓದುವುದು ಮತ್ತು ಪಾರ್ಸ್ ಮಾಡುವುದು ಎಂಬುದನ್ನು ಸರಳವಾಗಿ ತೋರಿಸುತ್ತದೆ:

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

ಸ್ಪಾರ್ಕ್‌ಗೆ ಡೇಟಾವನ್ನು ಲಭ್ಯವಾಗುವಂತೆ ಮಾಡಲು ಇದು ಸಾಕು.

ಪ್ರಾಯೋಗಿಕವಾಗಿ, ಫೋಲ್ಡರ್‌ನಿಂದ JSON ಫೈಲ್‌ಗಳನ್ನು ಓದುವುದಕ್ಕಿಂತ ಮತ್ತು ಡೇಟಾಫ್ರೇಮ್ ಅನ್ನು ರಚಿಸುವುದಕ್ಕಿಂತ ಸ್ಕ್ರಿಪ್ಟ್ ಹೆಚ್ಚು ಸಂಕೀರ್ಣವಾಗಿದೆ. ಪರಿಸ್ಥಿತಿಯು ಈ ರೀತಿ ಕಾಣುತ್ತದೆ: ಈಗಾಗಲೇ ಒಂದು ನಿರ್ದಿಷ್ಟ ಅಂಗಡಿಯ ಮುಂಭಾಗವಿದೆ, ಪ್ರತಿದಿನ ಹೊಸ ಡೇಟಾ ಬರುತ್ತದೆ, ಅವುಗಳನ್ನು ಅಂಗಡಿಯ ಮುಂಭಾಗಕ್ಕೆ ಸೇರಿಸಬೇಕಾಗಿದೆ, ಯೋಜನೆಯು ಭಿನ್ನವಾಗಿರಬಹುದು ಎಂಬುದನ್ನು ಮರೆಯಬಾರದು.

ಪ್ರದರ್ಶನವನ್ನು ನಿರ್ಮಿಸುವ ಸಾಮಾನ್ಯ ಯೋಜನೆ ಹೀಗಿದೆ:

1 ಹಂತ. ನಂತರದ ದೈನಂದಿನ ಮರುಲೋಡ್‌ನೊಂದಿಗೆ ಡೇಟಾವನ್ನು Hadoop ಗೆ ಲೋಡ್ ಮಾಡಲಾಗುತ್ತದೆ ಮತ್ತು ಹೊಸ ವಿಭಾಗಕ್ಕೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ಇದು ದಿನದ ಮೂಲಕ ವಿಭಜಿಸಲಾದ ಆರಂಭಿಕ ಡೇಟಾವನ್ನು ಹೊಂದಿರುವ ಫೋಲ್ಡರ್ ಅನ್ನು ತಿರುಗಿಸುತ್ತದೆ.

2 ಹಂತ. ಆರಂಭಿಕ ಲೋಡ್ ಸಮಯದಲ್ಲಿ, ಈ ಫೋಲ್ಡರ್ ಅನ್ನು ಸ್ಪಾರ್ಕ್ ಓದುತ್ತದೆ ಮತ್ತು ಪಾರ್ಸ್ ಮಾಡುತ್ತದೆ. ಪರಿಣಾಮವಾಗಿ ಡೇಟಾಫ್ರೇಮ್ ಅನ್ನು ಪಾರ್ಸ್ ಮಾಡಬಹುದಾದ ಸ್ವರೂಪದಲ್ಲಿ ಉಳಿಸಲಾಗುತ್ತದೆ, ಉದಾಹರಣೆಗೆ, ಪ್ಯಾರ್ಕ್ವೆಟ್‌ನಲ್ಲಿ, ನಂತರ ಅದನ್ನು ಇಂಪಾಲಾಕ್ಕೆ ಆಮದು ಮಾಡಿಕೊಳ್ಳಬಹುದು. ಇದು ಈ ಹಂತದವರೆಗೆ ಸಂಗ್ರಹವಾಗಿರುವ ಎಲ್ಲಾ ಡೇಟಾದೊಂದಿಗೆ ಟಾರ್ಗೆಟ್ ಶೋಕೇಸ್ ಅನ್ನು ರಚಿಸುತ್ತದೆ.

3 ಹಂತ. ಪ್ರತಿ ದಿನ ಅಂಗಡಿಯ ಮುಂಭಾಗವನ್ನು ನವೀಕರಿಸುವ ಡೌನ್‌ಲೋಡ್ ಅನ್ನು ರಚಿಸಲಾಗಿದೆ.
ಹೆಚ್ಚುತ್ತಿರುವ ಲೋಡಿಂಗ್, ಶೋಕೇಸ್ ಅನ್ನು ವಿಭಜಿಸುವ ಅಗತ್ಯತೆ ಮತ್ತು ಶೋಕೇಸ್ನ ಸಾಮಾನ್ಯ ಯೋಜನೆಯನ್ನು ನಿರ್ವಹಿಸುವ ಪ್ರಶ್ನೆ ಇದೆ.

ಒಂದು ಉದಾಹರಣೆಯನ್ನು ತೆಗೆದುಕೊಳ್ಳೋಣ. ರೆಪೊಸಿಟರಿಯನ್ನು ನಿರ್ಮಿಸುವ ಮೊದಲ ಹಂತವನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗಿದೆ ಮತ್ತು JSON ಫೈಲ್‌ಗಳನ್ನು ಫೋಲ್ಡರ್‌ಗೆ ಅಪ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ ಎಂದು ಹೇಳೋಣ.

ಅವರಿಂದ ಡೇಟಾಫ್ರೇಮ್ ಅನ್ನು ರಚಿಸುವುದು, ನಂತರ ಅದನ್ನು ಶೋಕೇಸ್ ಆಗಿ ಉಳಿಸುವುದು ಸಮಸ್ಯೆಯಲ್ಲ. ಇದು ಸ್ಪಾರ್ಕ್ ದಸ್ತಾವೇಜನ್ನು ಸುಲಭವಾಗಿ ಕಂಡುಹಿಡಿಯಬಹುದಾದ ಮೊದಲ ಹಂತವಾಗಿದೆ:

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 ಅನ್ನು ಓದುತ್ತೇವೆ ಮತ್ತು ಪಾರ್ಸ್ ಮಾಡಿದ್ದೇವೆ, ನಂತರ ನಾವು ಡೇಟಾಫ್ರೇಮ್ ಅನ್ನು ಪ್ಯಾರ್ಕ್ವೆಟ್ ಆಗಿ ಉಳಿಸುತ್ತೇವೆ, ಯಾವುದೇ ಅನುಕೂಲಕರ ರೀತಿಯಲ್ಲಿ ಅದನ್ನು ಹೈವ್‌ನಲ್ಲಿ ನೋಂದಾಯಿಸುತ್ತೇವೆ:

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

ನಾವು ಕಿಟಕಿಯನ್ನು ಪಡೆಯುತ್ತೇವೆ.

ಆದರೆ, ಮರುದಿನ, ಮೂಲದಿಂದ ಹೊಸ ಡೇಟಾವನ್ನು ಸೇರಿಸಲಾಯಿತು. ನಾವು JSON ಜೊತೆಗೆ ಫೋಲ್ಡರ್ ಅನ್ನು ಹೊಂದಿದ್ದೇವೆ ಮತ್ತು ಈ ಫೋಲ್ಡರ್‌ನಿಂದ ಶೋಕೇಸ್ ಅನ್ನು ರಚಿಸಿದ್ದೇವೆ. ಮೂಲದಿಂದ ಮುಂದಿನ ಬ್ಯಾಚ್ ಡೇಟಾವನ್ನು ಲೋಡ್ ಮಾಡಿದ ನಂತರ, ಡೇಟಾ ಮಾರ್ಟ್ ಒಂದು ದಿನದ ಮೌಲ್ಯದ ಡೇಟಾವನ್ನು ಕಾಣೆಯಾಗಿದೆ.

ತಾರ್ಕಿಕ ಪರಿಹಾರವೆಂದರೆ ಅಂಗಡಿಯ ಮುಂಭಾಗವನ್ನು ದಿನದಿಂದ ವಿಭಜಿಸುವುದು, ಇದು ಪ್ರತಿ ಮರುದಿನ ಹೊಸ ವಿಭಾಗವನ್ನು ಸೇರಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರ ಕಾರ್ಯವಿಧಾನವು ಚೆನ್ನಾಗಿ ತಿಳಿದಿದೆ, ಸ್ಪಾರ್ಕ್ ವಿಭಾಗಗಳನ್ನು ಪ್ರತ್ಯೇಕವಾಗಿ ಬರೆಯಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ.

ಮೊದಲಿಗೆ, ನಾವು ಆರಂಭಿಕ ಲೋಡ್ ಅನ್ನು ಮಾಡುತ್ತೇವೆ, ಮೇಲೆ ವಿವರಿಸಿದಂತೆ ಡೇಟಾವನ್ನು ಉಳಿಸುತ್ತೇವೆ, ವಿಭಜನೆಯನ್ನು ಮಾತ್ರ ಸೇರಿಸುತ್ತೇವೆ. ಈ ಕ್ರಿಯೆಯನ್ನು ಅಂಗಡಿಯ ಮುಂಭಾಗದ ಪ್ರಾರಂಭ ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ ಮತ್ತು ಇದನ್ನು ಒಮ್ಮೆ ಮಾತ್ರ ಮಾಡಲಾಗುತ್ತದೆ:

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

ಮರುದಿನ, ನಾವು ಹೊಸ ವಿಭಾಗವನ್ನು ಮಾತ್ರ ಲೋಡ್ ಮಾಡುತ್ತೇವೆ:

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

ಸ್ಕೀಮಾವನ್ನು ನವೀಕರಿಸಲು ಹೈವ್‌ನಲ್ಲಿ ಮರು-ನೋಂದಣಿ ಮಾಡಿಕೊಳ್ಳುವುದು ಮಾತ್ರ ಉಳಿದಿದೆ.
ಆದಾಗ್ಯೂ, ಇಲ್ಲಿ ಸಮಸ್ಯೆಗಳು ಉದ್ಭವಿಸುತ್ತವೆ.

ಮೊದಲ ಸಮಸ್ಯೆ. ಶೀಘ್ರದಲ್ಲೇ ಅಥವಾ ನಂತರ, ಪರಿಣಾಮವಾಗಿ ಪ್ಯಾರ್ಕ್ವೆಟ್ ಅನ್ನು ಓದಲಾಗುವುದಿಲ್ಲ. ಪ್ಯಾರ್ಕ್ವೆಟ್ ಮತ್ತು JSON ಖಾಲಿ ಜಾಗಗಳನ್ನು ಹೇಗೆ ವಿಭಿನ್ನವಾಗಿ ಪರಿಗಣಿಸುತ್ತದೆ ಎಂಬುದು ಇದಕ್ಕೆ ಕಾರಣ.

ಒಂದು ವಿಶಿಷ್ಟ ಸನ್ನಿವೇಶವನ್ನು ಪರಿಗಣಿಸೋಣ. ಉದಾಹರಣೆಗೆ, ನಿನ್ನೆ JSON ಆಗಮಿಸುತ್ತದೆ:

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

ಮತ್ತು ಇಂದು ಅದೇ JSON ಈ ರೀತಿ ಕಾಣುತ್ತದೆ:

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

ನಾವು ಎರಡು ವಿಭಿನ್ನ ವಿಭಾಗಗಳನ್ನು ಹೊಂದಿದ್ದೇವೆ ಎಂದು ಹೇಳೋಣ, ಪ್ರತಿಯೊಂದೂ ಒಂದು ಸಾಲಿನೊಂದಿಗೆ.
ನಾವು ಸಂಪೂರ್ಣ ಮೂಲ ಡೇಟಾವನ್ನು ಓದಿದಾಗ, ಸ್ಪಾರ್ಕ್ ಪ್ರಕಾರವನ್ನು ನಿರ್ಧರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ ಮತ್ತು "a" ಎಂಬುದು "ರಚನೆ" ಪ್ರಕಾರದ ಕ್ಷೇತ್ರವಾಗಿದೆ, INT ಪ್ರಕಾರದ "b" ನೊಂದಿಗೆ ನೆಸ್ಟೆಡ್ ಕ್ಷೇತ್ರವಾಗಿದೆ ಎಂದು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುತ್ತದೆ. ಆದರೆ, ಪ್ರತಿ ವಿಭಾಗವನ್ನು ಪ್ರತ್ಯೇಕವಾಗಿ ಉಳಿಸಿದರೆ, ನಾವು ಹೊಂದಾಣಿಕೆಯಾಗದ ವಿಭಜನಾ ಯೋಜನೆಗಳೊಂದಿಗೆ ಪ್ಯಾರ್ಕ್ವೆಟ್ ಅನ್ನು ಪಡೆಯುತ್ತೇವೆ:

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

ಈ ಪರಿಸ್ಥಿತಿಯು ಚೆನ್ನಾಗಿ ತಿಳಿದಿದೆ, ಆದ್ದರಿಂದ ಒಂದು ಆಯ್ಕೆಯನ್ನು ವಿಶೇಷವಾಗಿ ಸೇರಿಸಲಾಗಿದೆ - ಮೂಲ ಡೇಟಾವನ್ನು ಪಾರ್ಸ್ ಮಾಡುವಾಗ, ಖಾಲಿ ಕ್ಷೇತ್ರಗಳನ್ನು ತೆಗೆದುಹಾಕಿ:

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

ಈ ಸಂದರ್ಭದಲ್ಲಿ, ಪ್ಯಾರ್ಕ್ವೆಟ್ ಒಟ್ಟಿಗೆ ಓದಬಹುದಾದ ವಿಭಾಗಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ.
ಆಚರಣೆಯಲ್ಲಿ ಇದನ್ನು ಮಾಡಿದವರು ಇಲ್ಲಿ ಕಹಿಯಾಗಿ ನಗುತ್ತಾರೆ. ಏಕೆ? ಹೌದು, ಏಕೆಂದರೆ ಇನ್ನೂ ಎರಡು ಸನ್ನಿವೇಶಗಳು ಇರುವ ಸಾಧ್ಯತೆಯಿದೆ. ಅಥವಾ ಮೂರು. ಅಥವಾ ನಾಲ್ಕು. ಮೊದಲನೆಯದು, ಬಹುತೇಕ ಖಚಿತವಾಗಿ ಸಂಭವಿಸುತ್ತದೆ, ವಿಭಿನ್ನ JSON ಫೈಲ್‌ಗಳಲ್ಲಿ ಸಂಖ್ಯಾ ಪ್ರಕಾರಗಳು ವಿಭಿನ್ನವಾಗಿ ಕಾಣುತ್ತವೆ. ಉದಾಹರಣೆಗೆ, {intField: 1} ಮತ್ತು {intField: 1.1}. ಅಂತಹ ಕ್ಷೇತ್ರಗಳು ಒಂದು ವಿಭಾಗದಲ್ಲಿ ಕಂಡುಬಂದರೆ, ಸ್ಕೀಮಾ ವಿಲೀನವು ಎಲ್ಲವನ್ನೂ ಸರಿಯಾಗಿ ಓದುತ್ತದೆ, ಇದು ಅತ್ಯಂತ ನಿಖರವಾದ ಪ್ರಕಾರಕ್ಕೆ ಕಾರಣವಾಗುತ್ತದೆ. ಆದರೆ ವಿಭಿನ್ನವಾದವುಗಳಲ್ಲಿ, ಒಂದು ಇಂಟ್ಫೀಲ್ಡ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ: ಇಂಟ್, ಮತ್ತು ಇನ್ನೊಂದು ಇಂಟ್ಫೀಲ್ಡ್: ಡಬಲ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ.

ಈ ಪರಿಸ್ಥಿತಿಯನ್ನು ನಿಭಾಯಿಸಲು ಈ ಕೆಳಗಿನ ಧ್ವಜವಿದೆ:

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

ಈಗ ನಾವು ಒಂದು ಫೋಲ್ಡರ್ ಅನ್ನು ಹೊಂದಿದ್ದೇವೆ, ಅಲ್ಲಿ ವಿಭಾಗಗಳನ್ನು ಒಂದೇ ಡೇಟಾಫ್ರೇಮ್ನಲ್ಲಿ ಓದಬಹುದು ಮತ್ತು ಸಂಪೂರ್ಣ ಪ್ರದರ್ಶನದ ಮಾನ್ಯವಾದ ಪ್ಯಾರ್ಕ್ವೆಟ್ ಅನ್ನು ಓದಬಹುದು. ಹೌದು? ಸಂ.

ನಾವು ಹೈವ್ನಲ್ಲಿ ಟೇಬಲ್ ಅನ್ನು ನೋಂದಾಯಿಸಿದ್ದೇವೆ ಎಂದು ನಾವು ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊಳ್ಳಬೇಕು. ಜೇನುಗೂಡು ಕ್ಷೇತ್ರದ ಹೆಸರುಗಳಲ್ಲಿ ಕೇಸ್ ಸೆನ್ಸಿಟಿವ್ ಅಲ್ಲ, ಆದರೆ ಪ್ಯಾರ್ಕ್ವೆಟ್ ಕೇಸ್ ಸೆನ್ಸಿಟಿವ್ ಆಗಿದೆ. ಆದ್ದರಿಂದ, ಸ್ಕೀಮಾಗಳೊಂದಿಗಿನ ವಿಭಾಗಗಳು: field1: int, ಮತ್ತು Field1: int ಹೈವ್‌ಗೆ ಒಂದೇ ಆಗಿರುತ್ತವೆ, ಆದರೆ ಸ್ಪಾರ್ಕ್‌ಗೆ ಅಲ್ಲ. ಕ್ಷೇತ್ರದ ಹೆಸರುಗಳನ್ನು ಸಣ್ಣ ಅಕ್ಷರಕ್ಕೆ ಪರಿವರ್ತಿಸಲು ಮರೆಯಬೇಡಿ.

ಅದರ ನಂತರ, ಎಲ್ಲವೂ ಸರಿಯಾಗಿದೆ ಎಂದು ತೋರುತ್ತದೆ.

ಆದಾಗ್ಯೂ, ಎಲ್ಲವೂ ಅಷ್ಟು ಸುಲಭವಲ್ಲ. ಎರಡನೆಯದು, ಪ್ರಸಿದ್ಧವಾದ ಸಮಸ್ಯೆಯೂ ಇದೆ. ಪ್ರತಿ ಹೊಸ ವಿಭಾಗವನ್ನು ಪ್ರತ್ಯೇಕವಾಗಿ ಉಳಿಸಿರುವುದರಿಂದ, ವಿಭಜನಾ ಫೋಲ್ಡರ್ ಸ್ಪಾರ್ಕ್ ಸೇವಾ ಫೈಲ್‌ಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ, ಉದಾಹರಣೆಗೆ, _SUCCESS ಕಾರ್ಯಾಚರಣೆಯ ಯಶಸ್ಸಿನ ಫ್ಲ್ಯಾಗ್. ಪ್ಯಾರ್ಕ್ವೆಟ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸುವಾಗ ಇದು ದೋಷಕ್ಕೆ ಕಾರಣವಾಗುತ್ತದೆ. ಇದನ್ನು ತಪ್ಪಿಸಲು, ಫೋಲ್ಡರ್‌ಗೆ ಸೇವಾ ಫೈಲ್‌ಗಳನ್ನು ಸೇರಿಸದಂತೆ ಸ್ಪಾರ್ಕ್ ಅನ್ನು ತಡೆಯಲು ನೀವು ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ:

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

ಈಗ ಪ್ರತಿದಿನ ಹೊಸ ಪ್ಯಾರ್ಕ್ವೆಟ್ ವಿಭಾಗವನ್ನು ಟಾರ್ಗೆಟ್ ಶೋಕೇಸ್ ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ, ಅಲ್ಲಿ ದಿನದ ಪಾರ್ಸ್ ಮಾಡಿದ ಡೇಟಾ ಇದೆ. ಡೇಟಾ ಪ್ರಕಾರದ ಸಂಘರ್ಷದೊಂದಿಗೆ ಯಾವುದೇ ವಿಭಾಗಗಳಿಲ್ಲ ಎಂದು ನಾವು ಮುಂಚಿತವಾಗಿ ಕಾಳಜಿ ವಹಿಸಿದ್ದೇವೆ.

ಆದರೆ, ನಮಗೆ ಮೂರನೇ ಸಮಸ್ಯೆ ಇದೆ. ಈಗ ಸಾಮಾನ್ಯ ಸ್ಕೀಮಾ ತಿಳಿದಿಲ್ಲ, ಮೇಲಾಗಿ, ಹೈವ್‌ನಲ್ಲಿನ ಟೇಬಲ್ ತಪ್ಪಾದ ಸ್ಕೀಮಾವನ್ನು ಹೊಂದಿದೆ, ಏಕೆಂದರೆ ಪ್ರತಿ ಹೊಸ ವಿಭಾಗವು ಸ್ಕೀಮಾದಲ್ಲಿ ಅಸ್ಪಷ್ಟತೆಯನ್ನು ಪರಿಚಯಿಸುತ್ತದೆ.

ನೀವು ಟೇಬಲ್ ಅನ್ನು ಮರು-ನೋಂದಣಿ ಮಾಡಬೇಕಾಗಿದೆ. ಇದನ್ನು ಸರಳವಾಗಿ ಮಾಡಬಹುದು: ಸ್ಟೋರ್‌ಫ್ರಂಟ್‌ನ ಪ್ಯಾರ್ಕ್ವೆಟ್ ಅನ್ನು ಮತ್ತೊಮ್ಮೆ ಓದಿ, ಸ್ಕೀಮಾವನ್ನು ತೆಗೆದುಕೊಂಡು ಅದರ ಆಧಾರದ ಮೇಲೆ ಡಿಡಿಎಲ್ ಅನ್ನು ರಚಿಸಿ, ಅದರೊಂದಿಗೆ ಹೈವ್‌ನಲ್ಲಿ ಫೋಲ್ಡರ್ ಅನ್ನು ಬಾಹ್ಯ ಕೋಷ್ಟಕವಾಗಿ ಮರು-ನೋಂದಣಿ ಮಾಡಲು, ಗುರಿ ಅಂಗಡಿಯ ಮುಂಭಾಗದ ಸ್ಕೀಮಾವನ್ನು ನವೀಕರಿಸಿ.

ನಮಗೆ ನಾಲ್ಕನೆಯ ಸಮಸ್ಯೆ ಇದೆ. ನಾವು ಮೊದಲ ಬಾರಿಗೆ ಟೇಬಲ್ ಅನ್ನು ನೋಂದಾಯಿಸಿದಾಗ, ನಾವು ಸ್ಪಾರ್ಕ್ ಅನ್ನು ಅವಲಂಬಿಸಿದ್ದೇವೆ. ಈಗ ನಾವು ಅದನ್ನು ನಾವೇ ಮಾಡುತ್ತೇವೆ ಮತ್ತು ಪ್ಯಾರ್ಕ್ವೆಟ್ ಕ್ಷೇತ್ರಗಳು ಜೇನುಗೂಡಿಗೆ ಅನುಮತಿಸದ ಅಕ್ಷರಗಳೊಂದಿಗೆ ಪ್ರಾರಂಭವಾಗಬಹುದು ಎಂಬುದನ್ನು ನಾವು ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊಳ್ಳಬೇಕು. ಉದಾಹರಣೆಗೆ, "corrupt_record" ಕ್ಷೇತ್ರದಲ್ಲಿ ಪಾರ್ಸ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗದ ಸಾಲುಗಳನ್ನು ಸ್ಪಾರ್ಕ್ ಹೊರಹಾಕುತ್ತದೆ. ಅಂತಹ ಜಾಗವನ್ನು ತಪ್ಪಿಸಿಕೊಳ್ಳದೆ ಜೇನುಗೂಡಿನಲ್ಲಿ ನೋಂದಾಯಿಸಲಾಗುವುದಿಲ್ಲ.

ಇದನ್ನು ತಿಳಿದುಕೊಂಡು, ನಾವು ಯೋಜನೆಯನ್ನು ಪಡೆಯುತ್ತೇವೆ:

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(",", ",`").replace("array<`", "array<") ಸುರಕ್ಷಿತ DDL ಮಾಡುತ್ತದೆ, ಅಂದರೆ ಬದಲಿಗೆ:

create table tname (_field1 string, 1field string)

"_field1, 1field" ನಂತಹ ಕ್ಷೇತ್ರದ ಹೆಸರುಗಳೊಂದಿಗೆ, ಕ್ಷೇತ್ರದ ಹೆಸರುಗಳು ತಪ್ಪಿಸಿಕೊಂಡ ಸ್ಥಳದಲ್ಲಿ ಸುರಕ್ಷಿತ DDL ಅನ್ನು ತಯಾರಿಸಲಾಗುತ್ತದೆ: ಟೇಬಲ್ `tname` (`_field1` string, `1field` string) ರಚಿಸಿ.

ಪ್ರಶ್ನೆ ಉದ್ಭವಿಸುತ್ತದೆ: ಸಂಪೂರ್ಣ ಸ್ಕೀಮಾದೊಂದಿಗೆ (pf ಕೋಡ್‌ನಲ್ಲಿ) ಡೇಟಾಫ್ರೇಮ್ ಅನ್ನು ಸರಿಯಾಗಿ ಪಡೆಯುವುದು ಹೇಗೆ? ಈ ಪಿಎಫ್ ಅನ್ನು ಹೇಗೆ ಪಡೆಯುವುದು? ಇದು ಐದನೇ ಸಮಸ್ಯೆ. ಟಾರ್ಗೆಟ್ ಶೋಕೇಸ್‌ನ ಪ್ಯಾರ್ಕ್ವೆಟ್ ಫೈಲ್‌ಗಳೊಂದಿಗೆ ಫೋಲ್ಡರ್‌ನಿಂದ ಎಲ್ಲಾ ವಿಭಾಗಗಳ ಸ್ಕೀಮ್ ಅನ್ನು ಪುನಃ ಓದುವುದೇ? ಈ ವಿಧಾನವು ಸುರಕ್ಷಿತವಾಗಿದೆ, ಆದರೆ ಕಷ್ಟಕರವಾಗಿದೆ.

ಸ್ಕೀಮಾ ಈಗಾಗಲೇ ಹೈವ್‌ನಲ್ಲಿದೆ. ಸಂಪೂರ್ಣ ಟೇಬಲ್ ಮತ್ತು ಹೊಸ ವಿಭಾಗದ ಸ್ಕೀಮಾವನ್ನು ಸಂಯೋಜಿಸುವ ಮೂಲಕ ನೀವು ಹೊಸ ಸ್ಕೀಮಾವನ್ನು ಪಡೆಯಬಹುದು. ಆದ್ದರಿಂದ ನೀವು ಹೈವ್‌ನಿಂದ ಟೇಬಲ್ ಸ್ಕೀಮಾವನ್ನು ತೆಗೆದುಕೊಳ್ಳಬೇಕು ಮತ್ತು ಅದನ್ನು ಹೊಸ ವಿಭಾಗದ ಸ್ಕೀಮಾದೊಂದಿಗೆ ಸಂಯೋಜಿಸಬೇಕು. ಹೈವ್‌ನಿಂದ ಪರೀಕ್ಷಾ ಮೆಟಾಡೇಟಾವನ್ನು ಓದುವ ಮೂಲಕ, ಅದನ್ನು ತಾತ್ಕಾಲಿಕ ಫೋಲ್ಡರ್‌ಗೆ ಉಳಿಸುವ ಮೂಲಕ ಮತ್ತು ಎರಡೂ ವಿಭಾಗಗಳನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಓದಲು ಸ್ಪಾರ್ಕ್ ಬಳಸುವ ಮೂಲಕ ಇದನ್ನು ಮಾಡಬಹುದು.

ವಾಸ್ತವವಾಗಿ, ನಿಮಗೆ ಅಗತ್ಯವಿರುವ ಎಲ್ಲವೂ ಇದೆ: ಹೈವ್‌ನಲ್ಲಿನ ಮೂಲ ಟೇಬಲ್ ಸ್ಕೀಮಾ ಮತ್ತು ಹೊಸ ವಿಭಾಗ. ನಮ್ಮ ಬಳಿ ಡೇಟಾ ಕೂಡ ಇದೆ. ಇದು ಹೊಸ ಸ್ಕೀಮಾವನ್ನು ಪಡೆಯಲು ಮಾತ್ರ ಉಳಿದಿದೆ, ಇದು ಸ್ಟೋರ್‌ಫ್ರಂಟ್ ಸ್ಕೀಮಾ ಮತ್ತು ರಚಿಸಿದ ವಿಭಾಗದಿಂದ ಹೊಸ ಕ್ಷೇತ್ರಗಳನ್ನು ಸಂಯೋಜಿಸುತ್ತದೆ:

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 ಅನ್ನು ರಚಿಸುತ್ತೇವೆ.
ಇಡೀ ಸರಪಳಿಯು ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಿದರೆ, ಅವುಗಳೆಂದರೆ, ಪ್ರಾರಂಭಿಸುವ ಲೋಡ್ ಮತ್ತು ಹೈವ್‌ನಲ್ಲಿ ಸರಿಯಾಗಿ ರಚಿಸಲಾದ ಟೇಬಲ್, ನಂತರ ನಾವು ನವೀಕರಿಸಿದ ಟೇಬಲ್ ಸ್ಕೀಮಾವನ್ನು ಪಡೆಯುತ್ತೇವೆ.

ಮತ್ತು ಕೊನೆಯ ಸಮಸ್ಯೆಯೆಂದರೆ ನೀವು ಹೈವ್ ಟೇಬಲ್‌ಗೆ ವಿಭಾಗವನ್ನು ಸೇರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ಏಕೆಂದರೆ ಅದು ಮುರಿದುಹೋಗುತ್ತದೆ. ಹೈವ್ ಅನ್ನು ಅದರ ವಿಭಜನಾ ರಚನೆಯನ್ನು ಸರಿಪಡಿಸಲು ನೀವು ಒತ್ತಾಯಿಸಬೇಕಾಗಿದೆ:

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

JSON ಅನ್ನು ಓದುವ ಮತ್ತು ಅದರ ಆಧಾರದ ಮೇಲೆ ಅಂಗಡಿಯ ಮುಂಭಾಗವನ್ನು ರಚಿಸುವ ಸರಳ ಕಾರ್ಯವು ಹಲವಾರು ಸೂಚ್ಯ ತೊಂದರೆಗಳನ್ನು ನಿವಾರಿಸುವಲ್ಲಿ ಕಾರಣವಾಗುತ್ತದೆ, ಇದಕ್ಕಾಗಿ ನೀವು ಪ್ರತ್ಯೇಕವಾಗಿ ನೋಡಬೇಕಾದ ಪರಿಹಾರಗಳು. ಮತ್ತು ಈ ಪರಿಹಾರಗಳು ಸರಳವಾಗಿದ್ದರೂ, ಅವುಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಸಾಕಷ್ಟು ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ.

ಪ್ರದರ್ಶನದ ನಿರ್ಮಾಣವನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು, ನಾನು ಮಾಡಬೇಕಾಗಿತ್ತು:

  • ಶೋಕೇಸ್‌ಗೆ ವಿಭಾಗಗಳನ್ನು ಸೇರಿಸಿ, ಸೇವಾ ಫೈಲ್‌ಗಳನ್ನು ತೊಡೆದುಹಾಕಲು
  • ಸ್ಪಾರ್ಕ್ ಟೈಪ್ ಮಾಡಿದ ಮೂಲ ಡೇಟಾದಲ್ಲಿ ಖಾಲಿ ಕ್ಷೇತ್ರಗಳೊಂದಿಗೆ ವ್ಯವಹರಿಸಿ
  • ಸರಳ ಪ್ರಕಾರಗಳನ್ನು ಸ್ಟ್ರಿಂಗ್‌ಗೆ ಬಿತ್ತರಿಸಿ
  • ಕ್ಷೇತ್ರದ ಹೆಸರುಗಳನ್ನು ಸಣ್ಣ ಅಕ್ಷರಕ್ಕೆ ಪರಿವರ್ತಿಸಿ
  • ಹೈವ್‌ನಲ್ಲಿ ಪ್ರತ್ಯೇಕ ಡೇಟಾ ಅಪ್‌ಲೋಡ್ ಮತ್ತು ಟೇಬಲ್ ನೋಂದಣಿ (DDL ಪೀಳಿಗೆ)
  • ಹೈವ್‌ಗೆ ಹೊಂದಿಕೆಯಾಗದ ಕ್ಷೇತ್ರದ ಹೆಸರುಗಳಿಂದ ತಪ್ಪಿಸಿಕೊಳ್ಳಲು ಮರೆಯಬೇಡಿ
  • ಹೈವ್‌ನಲ್ಲಿ ಟೇಬಲ್ ನೋಂದಣಿಯನ್ನು ನವೀಕರಿಸುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿಯಿರಿ

ಸಂಕ್ಷಿಪ್ತವಾಗಿ ಹೇಳುವುದಾದರೆ, ಅಂಗಡಿ ಕಿಟಕಿಗಳನ್ನು ನಿರ್ಮಿಸುವ ನಿರ್ಧಾರವು ಅನೇಕ ಮೋಸಗಳಿಂದ ತುಂಬಿದೆ ಎಂದು ನಾವು ಗಮನಿಸುತ್ತೇವೆ. ಆದ್ದರಿಂದ, ನೀವು ಅನುಷ್ಠಾನದಲ್ಲಿ ತೊಂದರೆಗಳನ್ನು ಎದುರಿಸಿದರೆ, ಯಶಸ್ವಿ ಪರಿಣತಿಯೊಂದಿಗೆ ಅನುಭವಿ ಪಾಲುದಾರರನ್ನು ಸಂಪರ್ಕಿಸುವುದು ಉತ್ತಮ.

ಈ ಲೇಖನವನ್ನು ಓದಿದ್ದಕ್ಕಾಗಿ ಧನ್ಯವಾದಗಳು, ಮಾಹಿತಿಯು ನಿಮಗೆ ಉಪಯುಕ್ತವಾಗಿದೆ ಎಂದು ನಾವು ಭಾವಿಸುತ್ತೇವೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ