الشهيرة: الشرارة تعمل مع dataframes ، والتي هي خوارزميات التحول. يتم إطلاق الخوارزمية في آخر لحظة من أجل "إعطاء مساحة أكبر" للتحسين وبسبب التحسين لتنفيذها بأكبر قدر ممكن من الكفاءة.
تحت الخفض ، سنقوم بتحليل كيفية تحليل استعلام SQL متعدد الصفحات إلى ذرات (دون فقدان الكفاءة) وكيفية تقليل وقت تنفيذ خط أنابيب ETL بشكل كبير نتيجة لذلك.
تقييم كسول
ميزة وظيفية مثيرة للاهتمام من الشرارة هي تقييم كسول: يتم تنفيذ التحويلات فقط عند الانتهاء من الإجراءات. كيف تعمل (تقريبًا): يتم "تجميع" الخوارزميات الخاصة بإنشاء إطارات البيانات التي تسبق الإجراء ، ويقوم المحسن بإنشاء الخوارزمية النهائية الأكثر كفاءة من وجهة نظره ، والتي تبدأ وتعطي النتيجة (الخوارزمية التي طلبها الإجراء).
ما هو مثير للاهتمام هنا في سياق عرضنا التقديمي: أي استعلام معقد يمكن أن يتحلل إلى "ذرات" دون فقدان الكفاءة. دعنا نحلل قليلا.
متعدد الصفحات SQL
هناك العديد من الأسباب التي تجعلنا نكتب استعلامات SQL "متعددة الصفحات" ، أحد أهمها ، على الأرجح ، الإحجام عن إنشاء كائنات وسيطة (الممانعة مدعومة بمتطلبات الكفاءة). فيما يلي مثال لطلب بحث معقد نسبيًا (بالطبع ، إنه بسيط للغاية ، ولكن لأغراض العرض التقديمي الإضافي ، سيكون لدينا ما يكفي).
qSel = """ select con.contract_id as con_contract_id, con.begin_date as con_begin_date, con.product_id as con_product_id, cst.contract_status_type_id as cst_status_type_id, sbj.subject_id as sbj_subject_id, sbj.subject_name as sbj_subject_name, pp.birth_date as pp_birth_date from kasko.contract con join kasko.contract_status cst on cst.contract_status_id = con.contract_status_id join kasko.subject sbj on sbj.subject_id = con.owner_subject_id left join kasko.physical_person pp on pp.subject_id = con.owner_subject_id """ dfSel = sp.sql(qSel)
ماذا نرى:
- يتم تحديد البيانات من عدة جداول
- يتم استخدام أنواع مختلفة من الصلة
- يتم توزيع الأعمدة القابلة للتحديد عن طريق تحديد جزء ، والانضمام إلى جزء (وأين جزء ، ولكن هنا ليس هنا - لقد قمت بإزالته للبساطة)
يمكن أن يتحلل هذا الاستعلام إلى طلبات بسيطة (على سبيل المثال ، اجمع بين جداول العقد والعقد ، وحفظ النتيجة في جدول مؤقت ، ثم ادمجها مع موضوع ، واحفظ النتيجة في جدول مؤقت ، إلخ). بالتأكيد ، عندما نقوم بإنشاء استعلامات معقدة حقًا ، فإننا نفعل ذلك ، وبعد ذلك - بعد تصحيح الأخطاء - نجمع كل هذا في كتلة متعددة الصفحات.
ما هو سيء هنا؟ لا شيء ، في الواقع ، كل شخص يعمل بهذا الشكل ويعتاد عليه.
ولكن هناك عيوب - أو بالأحرى ما يجب تحسينه - تابع القراءة.
نفس الاستعلام في شرارة
عند استخدام الشرارة للتحول ، بالطبع ، يمكنك فقط أخذ هذا الطلب وتنفيذه (وسيكون جيدًا ، في الواقع ، سننفذه أيضًا) ، لكن يمكنك أن تقلبه ، فلنجربه.
لنحلل هذا الاستعلام "المعقد" إلى "ذرات" - إطارات البيانات الأولية. سنحصل على أكبر عدد ممكن من عدد الجداول المتضمنة في الاستعلام (في هذه الحالة ، 4).
ها هم - "ذرات":
dfCon = sp.sql("""select contract_id as con_contract_id, begin_date as con_begin_date, product_id as con_product_id, owner_subject_id as con_owner_subject_id, contract_status_id as con_contract_status_id from kasko.contract""") dfCStat = sp.sql("""select contract_status_id as cst_status_id, contract_status_type_id as cst_status_type_id from kasko.contract_status""") dfSubj = sp.sql("""select subject_id as sbj_subject_id, subject_type_id as sbj_subject_type_id, subject_name as sbj_subject_name from kasko.subject""") dfPPers = sp.sql("""select subject_id as pp_subject_id, birth_date as pp_birth_date from kasko.physical_person""")
يتيح لك Spark الانضمام إليهم باستخدام تعبيرات مفصولة عن "الذرات" الفعلية ؛ دعنا نفعل ذلك:
con_stat = f.col("cst_status_id")==f.col("con_contract_status_id") con_subj_own = f.col("con_owner_subject_id")==f.col("sbj_subject_id") con_ppers_own = f.col("con_owner_subject_id")==f.col("pp_subject_id")
عندها سيبدو "الاستعلام المعقد" كما يلي:
dfAtom = dfCon.join(dfCStat,con_stat, "inner")\ .join(dfSubj,con_subj_own,"inner") \ .join(dfPPers,con_ppers_own, "left") \ .drop("con_contract_status_id","sbj_subject_type_id", "pp_subject_id","con_owner_subject_id","cst_status_id")
ما هو جيد هنا؟ للوهلة الأولى ، لا يوجد شيء ، بل هو العكس تمامًا: باستخدام SQL "معقدة" ، يمكنك فهم ما يحدث ، من خلال استعلامنا "الذري" ، يكون فهمك أكثر صعوبة ، تحتاج إلى إلقاء نظرة على "الذرات" والتعبيرات.
دعنا أولاً نتأكد من أن هذه الاستعلامات متكافئة - في كتاب المشتري حسب المرجع ، قدمت خططًا لتنفيذ كلا الاستعلامات (يمكن للفضوليين أن يجد 10 اختلافات ، لكن الجوهر - التكافؤ - واضح). هذه ، بالطبع ، ليست معجزة ، بل يجب أن تكون كذلك (انظر أعلاه للتقييم البطيء والتحسين).
ما لدينا في النهاية - الطلب "متعدد الصفحات" والطلب "الذري" يعملان بنفس الكفاءة (هذا مهم ، دون أن تفقد هذه الاعتبارات الإضافية معناها جزئيًا).
حسنًا ، دعنا الآن نعثر على الطريقة "الذرية" لبناء الاستعلامات.
ما هو "الذرة" (إطار البيانات الأولية) هو معرفتنا لمجموعة فرعية من مجال الموضوع (جزء من الجدول العلائقي). من خلال عزل هذه "الذرات" ، نقوم تلقائيًا (والأهم من ذلك خوارزمية واستنساخية) باختيار جزء مهم من الشيء الذي لا حدود له بالنسبة لنا والذي يطلق عليه "نموذج البيانات الفعلية".
ما هو التعبير الذي استخدمناه عند الانضمام؟ هذه هي أيضًا معرفة حول موضوع الموضوع - وهذا هو كيف ترتبط (كما هو موضح في التعبير) كيانات مجال الموضوع (الجداول في قاعدة البيانات).
أكرر - هذا أمر مهم - هذه "المعرفة" (الذرات والتعبيرات) تتحقق في التعليمات البرمجية القابلة للتنفيذ (وليس في المخطط أو الوصف اللفظي) ، هذا هو الكود الذي يتم تنفيذه في كل مرة يتم فيها تنفيذ خط أنابيب ETL (يتم أخذ المثال ، بالمناسبة ، من واقع الحياة).
الكود القابل للتنفيذ - كما نعلم من المبرمج النظيف - هو أحد التحف الفنية الموجودة بموضوعية والتي تدعي أنها "عنوان" الوثائق. أي أن استخدام "الذرات" يسمح لنا باتخاذ خطوة إلى الأمام في مثل هذه العملية الهامة مثل توثيق البيانات.
ماذا يمكن أن توجد في "الذرية"؟
تحسين الناقل
في الحياة الواقعية ، مهندس بيانات - بالمناسبة ، لم أقدم نفسي - يتكون خط أنابيب ETL من عشرات التحولات المشابهة لما سبق. غالبًا ما تتكرر الجداول فيها (يتم حسابي بطريقة ما في Excel - يتم استخدام بعض الجداول في 40٪ من الاستعلامات).
ماذا يحدث من حيث الكفاءة؟ فوضى - تتم قراءة نفس الجدول عدة مرات من المصدر ...
كيفية تحسينه؟ يحتوي Spark على آلية لتخزين إطارات البيانات مؤقتًا - يمكننا تحديد إطارات البيانات بشكل صريح والمبلغ الذي نريد الاحتفاظ به في ذاكرة التخزين المؤقت.
ما يتعين علينا القيام به من أجل هذا هو تحديد الجداول المكررة وإنشاء استعلامات بطريقة تقلل من الحجم الكلي لذاكرة التخزين المؤقت (لأن جميع الجداول ، بحكم تعريفها ، لن تنسجم معها ، ثم هناك بيانات كبيرة).
هل يمكن القيام بذلك باستخدام استعلامات SSQ متعددة الصفحات؟ نعم ، لكن ... معقدة بعض الشيء (ليس لدينا بالفعل إطارات بيانات هناك ، فقط الجداول ، ويمكن أيضًا تخزينها مؤقتًا - مجتمع الشرارة يعمل على ذلك).
هل يمكن القيام بذلك باستخدام الاستعلامات الذرية؟ نعم! وهذا ليس بالأمر الصعب ، نحتاج فقط إلى تعميم "الذرات" - إضافة الأعمدة المستخدمة في جميع استفسارات خط أنابيبنا إليهم. إذا كنت تفكر في ذلك ، فهذا "صحيح" من وجهة نظر الوثائق: إذا تم استخدام عمود في بعض الاستعلام (حتى لو كان في جزء المكان) ، فهذا جزء من بيانات موضوع الموضوع التي تهمنا.
وبعد ذلك كل شيء بسيط - نحن نقوم بتخزين مؤقت للذرات المكررة (إطارات البيانات) ، ونبني سلسلة من التحولات بحيث يكون تقاطع إطارات البيانات المخزنة مؤقتًا في حده الأدنى (هذا ليس تافهاً ، لكنه خوارزمي ، بالمناسبة).
ونحن نحصل على ناقل أكثر كفاءة "مجاني" تماما. بالإضافة إلى ذلك ، هناك قطعة أثرية مفيدة وهامة هي "التحضير" لتوثيق البيانات في مجال الموضوع.
Robotization والأتمتة
تعد الذرات أكثر عرضة للمعالجة التلقائية من "SQL كبيرة وقوية" - هيكلها بسيط وواضح ، الشرارة تقوم بالتحليل بالنسبة لنا (والتي بفضل خاص له) ، كما أنه يبني خطط الاستعلام ، ويحلل يمكنك إعادة ترتيب تسلسل معالجة الاستعلام تلقائيًا.
حتى هنا يمكنك لعب شيء ما.
في الختام
ربما أكون متفائلاً للغاية - يبدو لي أن هذا المسار (الانحلال في الاستعلام) يعمل أكثر من محاولة وصف مصدر البيانات بعد حدوثه. بالإضافة إلى ذلك - بالمناسبة ، ما هو استخدام "المضافات" - نحصل على زيادة في الكفاءة. لماذا أفكر في النهج الذري "العمل"؟ إنها جزء من العملية المنتظمة ، مما يعني أن القطع الأثرية الموصوفة لديها فرصة حقيقية لتكون ذات صلة على المدى الطويل.
ربما فاتني شيء - ساعد في العثور على (في التعليقات)؟