PostgreSQL Antipatterns: Sisyphus JOIN Arrays

في بعض الأحيان تنشأ مهمة "الغراء" لاختيار متكامل مع نفس البيانات "في الأعمدة" من المصفوفات الخطية التي تم تمريرها كمعلمات في استعلام SQL.

كيف يتم ذلك في بعض الأحيان:

WITH T1 AS ( SELECT row_number() OVER() rn , unnest v1 FROM unnest('{1,2,3,4}'::integer[]) ) , T2 AS ( SELECT row_number() OVER() rn , unnest v2 FROM unnest('{5,6}'::integer[]) ) SELECT T1.v1 , T2.v2 FROM T1 LEFT JOIN T2 USING(rn); 

 v1 | v2 ------- 1 | 5 2 | 6 3 | 4 | 

وهذا هو ، أولاً ، تم "توسيع" كل صفيف في العينة ، مرقمة ، ثم تم استخدام هذا الرقم كمفتاح اتصال CTE ...


[انظروا شرح.tensor.ru]

مع الاعتيادية


تم إنفاق أكثر من ربع الوقت على برنامج WindowAgg!

ولكن إذا استخدمنا إصدار PG لا يقل عن 9.4 ، فيمكننا استخدام WITH ORDINALITY لترقيم نتائج أي SRF ، بما في ذلك nnest:

 WITH T1 AS ( SELECT * FROM unnest('{1,2,3,4}'::integer[]) WITH ORDINALITY T(v1, rn) ) , T2 AS ( SELECT * FROM unnest('{5,6}'::integer[]) WITH ORDINALITY T(v2, rn) ) SELECT T1.v1 , T2.v2 FROM T1 LEFT JOIN T2 USING(rn); 

[انظروا شرح . tensor.ru] .

وبالتالي ، تخلصنا تمامًا من استخدام وظائف النافذة.

حجة متعددة UNNEST


ولكن من وجهة نظر الكفاءة ، ليس كل شيء جيدًا حتى الآن - فقد مضى نصف الوقت تقريبًا على Hash Left Join.

وانطلق المؤلف بوضوح من الافتراض بأن الصفيف الأول أطول تمامًا - لهذا السبب استخدم LEFT JOIN. لكن هذا الافتراض ليس صحيحًا دائمًا ويمكن أن يسبب مشاكل.

للالتفاف حوله ، سوف نستخدم nnest لعدة صفائف في نفس الوقت ، والتي ظهرت من نفس الإصدار 9.4:

 SELECT * FROM unnest( '{1,2,3,4}'::integer[] , '{5,6}'::integer[] ) T(v1, v2); 

نتيجة لذلك ، لم يبق شيء تقريبًا من الطلب ، ومن الخطة:

 Function Scan on t (cost=0.01..1.00 rows=100 width=8) (actual time=0.006..0.007 rows=4 loops=1) 

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

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


All Articles