ما يفسر الصمت وكيف نتحدث عنه

السؤال الكلاسيكي الذي يطرحه أحد المطورين إلى DBA أو مالك أعمال ، مستشار PostgreSQL ، يبدو دائمًا كما هو: "لماذا تعمل الاستعلامات في قاعدة البيانات لفترة طويلة؟"

مجموعة الأسباب التقليدية:

  • خوارزمية غير فعالة
    عندما قررت إنشاء JOE من عدة CTEs لبضع عشرات الآلاف من السجلات
  • إحصائيات غير ذات صلة
    إذا كان التوزيع الفعلي للبيانات في الجدول مختلفًا تمامًا عن آخر مرة جمعتها ANALYZE
  • "هفوة" من الموارد
    كما أن طاقة الحوسبة المخصصة لوحدة المعالجة المركزية ليست كافية بالفعل ، حيث يتم ضخ غيغابايت من الذاكرة باستمرار أو لا يواكب القرص قاعدة البيانات "مفضلة"
  • منع من العمليات المتنافسة

وإذا كان من الصعب للغاية التقاط الأقفال وتحليلها ، فبالنسبة إلى أي شيء آخر ، نحتاج إلى خطة استعلام يمكن الحصول عليها باستخدام عامل التشغيل EXPLAIN ( أفضل ، بالطبع ، بشكل فوري شرح (تحليل ، BUFFERS) ... ) أو وحدة نمطية auto_explain .

ولكن ، كما قال في نفس الوثائق ،
"فهم الخطة عبارة عن فن ، ولإتقانها ، أنت بحاجة إلى بعض الخبرة ، ..."
ولكن يمكنك الاستغناء عنها ، إذا كنت تستخدم الأداة الصحيحة!

ما شكل خطة الاستعلام عادة؟ شيء مثل هذا:

Index Scan using pg_class_relname_nsp_index on pg_class (actual time=0.049..0.050 rows=1 loops=1) Index Cond: (relname = $1) Filter: (oid = $0) Buffers: shared hit=4 InitPlan 1 (returns $0,$1) -> Limit (actual time=0.019..0.020 rows=1 loops=1) Buffers: shared hit=1 -> Seq Scan on pg_class pg_class_1 (actual time=0.015..0.015 rows=1 loops=1) Filter: (relkind = 'r'::"char") Rows Removed by Filter: 5 Buffers: shared hit=1 

أو مثل هذا:

 "Append (cost=868.60..878.95 rows=2 width=233) (actual time=0.024..0.144 rows=2 loops=1)" " Buffers: shared hit=3" " CTE cl" " -> Seq Scan on pg_class (cost=0.00..868.60 rows=9972 width=537) (actual time=0.016..0.042 rows=101 loops=1)" " Buffers: shared hit=3" " -> Limit (cost=0.00..0.10 rows=1 width=233) (actual time=0.023..0.024 rows=1 loops=1)" " Buffers: shared hit=1" " -> CTE Scan on cl (cost=0.00..997.20 rows=9972 width=233) (actual time=0.021..0.021 rows=1 loops=1)" " Buffers: shared hit=1" " -> Limit (cost=10.00..10.10 rows=1 width=233) (actual time=0.117..0.118 rows=1 loops=1)" " Buffers: shared hit=2" " -> CTE Scan on cl cl_1 (cost=0.00..997.20 rows=9972 width=233) (actual time=0.001..0.104 rows=101 loops=1)" " Buffers: shared hit=2" "Planning Time: 0.634 ms" "Execution Time: 0.248 ms" 

ولكن قراءة الخطة مع النص "من الورقة" صعب للغاية ومحبوب:

  • يعرض العقدة مجموع موارد الشجرة الفرعية
    أي لفهم مقدار الوقت المستغرق لتنفيذ عقدة معينة ، أو بالضبط مقدار مقدار هذه القراءة من الجدول الذي أثار البيانات من القرص - تحتاج إلى طرح أحدها بطريقة أخرى بطريقة أو بأخرى
  • يجب ضرب وقت العقدة بحلقات
    نعم ، الطرح ليس العملية الأكثر صعوبة التي يجب القيام بها "في العقل" - بعد كل شيء ، تتم الإشارة إلى متوسط ​​وقت التشغيل لتنفيذ عقدة واحدة ، وقد يكون هناك المئات
  • حسنًا ، وهذا كله يجعل من الصعب الإجابة على السؤال الرئيسي - إذن من هو "الحلقة الأضعف" ؟

عندما حاولنا شرح كل هذا لعدة مئات من مطورينا ، أدركنا أنه من الخارج يبدو مثل هذا:

صورة

وهذا يعني أننا بحاجة ...

أداة


في ذلك ، حاولنا جمع كل الميكانيكا الرئيسية التي تساعد وفقًا للخطة ونطلب أن نفهم "من يقع اللوم وماذا يفعل". حسنًا ، شارك بعضًا من تجربتك مع المجتمع.
يجتمع واستخدام - illust.tensor.ru

خطط واضحة


هل من السهل فهم الخطة عندما تبدو هكذا؟

 Seq Scan on pg_class (actual time=0.009..1.304 rows=6609 loops=1) Buffers: shared hit=263 Planning Time: 0.108 ms Execution Time: 1.800 ms 

ليس حقا

لكن هكذا ، في شكل مختصر ، عندما يتم فصل المؤشرات الرئيسية - يكون الأمر أكثر وضوحًا بالفعل:

صورة

ولكن إذا كانت الخطة أكثر تعقيدًا ، فسيكون توزيع وقت توزيع البايت بواسطة العقد متاحًا للإنقاذ :

صورة

حسنًا ، بالنسبة إلى أصعب الخيارات ، يسارع مخطط التنفيذ للمساعدة في:

صورة

على سبيل المثال ، هناك مواقف غير تافهة تمامًا عندما يكون للخطة أكثر من جذر فعلي واحد:

صورةصورة

نصائح الهيكلية


حسنًا ، وإذا كانت البنية الكاملة للخطة ومواقعها المؤلمة قد وضعت بالفعل وضوحا - فلماذا لا تسليط الضوء عليها مع المطور واشرحها بـ "اللغة الروسية"؟

صورة لقد جمعنا بالفعل بضع عشرات من نماذج التوصيات هذه.

منشئ الاستعلامات


الآن ، إذا وضعت الاستعلام الأصلي على الخطة التي تم تحليلها ، يمكنك معرفة مقدار الوقت المستغرق لكل مشغل فردي - شيء مثل هذا:

صورة

... أو حتى مع ذلك:

صورة

استبدال المعلمات في الطلب


إذا لم "ترفق" طلب الخطة فقط ، ولكن أيضًا معلماتها من سطر التفاصيل في السجل ، يمكنك نسخه بالإضافة إلى ذلك في أحد الخيارات:

  • مع استبدال القيم في الطلب
    للتنفيذ المباشر على قاعدتها والمزيد من التنميط

     SELECT 'const', 'param'::text; 
  • مع استبدال القيمة عبر PREPARE / EXECUTE
    لمضاهاة عمل المجدول عندما يمكن تجاهل الجزء حدودي - على سبيل المثال ، عند العمل على الجداول المقسمة

     DEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text); 

خطط الخطط


إدراج وتحليل ومشاركتها مع الزملاء! ستبقى الخطط في الأرشيف ، ويمكنك العودة إليها لاحقًا: illust.tensor.ru/archive

ولكن إذا كنت لا تريد أن يرى الآخرون خطتك ، فلا تنسَ تحديد مربع الاختيار "عدم النشر في الأرشيف".

في المقالات التالية سوف أتحدث عن الصعوبات والحلول التي تنشأ في تحليل الخطة.

Source: https://habr.com/ru/post/ar477624/


All Articles