مائڪرو سروس آرڪيٽيڪچر ۾ آپريشنل اينالائيٽڪس: مدد ۽ فوري پوسٽ گريس FDW

Microservice فن تعمير، هن دنيا ۾ هر شيء وانگر، ان جا فائدا ۽ نقصان آهن. ڪجھ عمل ان سان آسان ٿي ويندا آھن، ٻيا وڌيڪ ڏکيو. ۽ تبديلي جي رفتار ۽ بهتر اسڪاليبلٽي جي خاطر، توهان کي قرباني ڏيڻ جي ضرورت آهي. انهن مان هڪ آهي تجزياتي جي وڌندڙ پيچيدگي. جيڪڏهن هڪ واحد ۾ سڀ عملياتي تجزياتي تجزياتي ريپليڪا ڏانهن SQL سوالن کي گھٽائي سگھجي ٿو، پوء هڪ گھڻائي خدمت آرڪيٽيڪچر ۾ هر خدمت جو پنهنجو ڊيٽابيس آهي ۽ اهو لڳي ٿو ته هڪ سوال نه ٿو ڪري سگهجي (يا شايد اهو ٿي سگهي ٿو؟). انهن لاءِ جيڪي دلچسپي رکن ٿا ته اسان پنهنجي ڪمپني ۾ آپريشنل اينالائيٽڪس جي مسئلي کي ڪيئن حل ڪيو ۽ اسان هن حل سان ڪيئن رهڻ سکيو - ڀليڪار.

مائڪرو سروس آرڪيٽيڪچر ۾ آپريشنل اينالائيٽڪس: مدد ۽ فوري پوسٽ گريس FDW
منهنجو نالو Pavel Sivash آهي، DomClick تي آئون هڪ ٽيم ۾ ڪم ڪريان ٿو جيڪا تجزياتي ڊيٽا گودام کي برقرار رکڻ جي ذميوار آهي. روايتي طور تي، اسان جي سرگرمين کي ڊيٽا انجنيئرنگ طور درجه بندي ڪري سگهجي ٿو، پر حقيقت ۾، ڪمن جي حد تمام وسيع آهي. ڊيٽا انجنيئرنگ لاءِ ETL/ELT معيار آهن، ڊيٽا جي تجزيي ۽ توهان جي پنهنجي اوزارن جي ترقي لاءِ اوزارن جي سپورٽ ۽ موافقت. خاص طور تي، آپريشنل رپورٽنگ لاءِ، اسان فيصلو ڪيو ته ”ڏسو“ ته اسان وٽ هڪ واحد آهي ۽ تجزيه نگارن کي هڪ ڊيٽابيس ڏيو جنهن ۾ اهي سڀ ڊيٽا هوندا جيڪي انهن جي ضرورت هوندي.

عام طور تي، اسان مختلف اختيارن تي غور ڪيو. اهو ممڪن هو ته هڪ مڪمل مخزن ٺاهڻ - اسان ڪوشش به ڪئي، پر، سچ پڇو ته، اسان منطق ۾ ڪافي بار بار تبديلين کي گڏ ڪرڻ جي قابل نه هئاسين، بلڪه سست رفتاري سان گڏ هڪ مخزن ٺاهڻ ۽ ان ۾ تبديليون ڪرڻ (جيڪڏهن ڪو ڪامياب ٿي ويو. ، تبصرن ۾ لکو ڪيئن). تجزيه نگارن کي اهو ٻڌائڻ ممڪن هو ته: ”يار، پيٿون سيکارو ۽ تجزياتي نقلن ڏانهن وڃو“، پر ڀرتي لاءِ اها هڪ اضافي گهرج آهي، ۽ لڳي ٿو ته جيڪڏهن ممڪن هجي ته ان کان پاسو ڪيو وڃي. اسان FDW (پرڏيهي ڊيٽا ريپر) ٽيڪنالاجي استعمال ڪرڻ جي ڪوشش ڪرڻ جو فيصلو ڪيو: بنيادي طور تي، هي هڪ معياري dblink آهي، جيڪو SQL معيار ۾ آهي، پر ان جي پنهنجي وڌيڪ آسان انٽرفيس سان. ان جي بنياد تي، اسان هڪ حل ڪيو، جيڪو آخرڪار پڪڙيو، ۽ اسان ان تي آباد ٿيا. ان جا تفصيل هڪ الڳ مضمون جو موضوع آهن، ۽ ٿي سگهي ٿو هڪ کان وڌيڪ، ڇاڪاڻ ته مان گهڻو ڪجهه ڳالهائڻ چاهيان ٿو: ڊيٽابيس اسڪيمن کي هم وقت سازي ڪرڻ کان وٺي ڪنٽرول تائين رسائي ۽ ذاتي ڊيٽا جي بي ترتيب ڪرڻ تائين. اهو پڻ هڪ رزرويشن ڪرڻ ضروري آهي ته هي حل حقيقي تجزياتي ڊيٽابيس ۽ ذخيرو لاء متبادل ناهي؛ اهو صرف هڪ مخصوص مسئلو حل ڪري ٿو.

مٿين سطح تي اهو هن طرح نظر اچي ٿو:

مائڪرو سروس آرڪيٽيڪچر ۾ آپريشنل اينالائيٽڪس: مدد ۽ فوري پوسٽ گريس FDW
اتي ھڪڙو PostgreSQL ڊيٽابيس آھي جتي صارف پنھنجي ڪم جي ڊيٽا کي ذخيرو ڪري سگھن ٿا، ۽ سڀ کان وڌيڪ ضروري آھي، سڀني خدمتن جي تجزياتي نقلن کي FDW ذريعي ھن ڊيٽابيس سان ڳنڍيل آھي. اهو ڪيترن ئي ڊيٽابيسن تي سوال لکڻ ممڪن بڻائي ٿو، ۽ اهو مسئلو ناهي ته اهو ڇا آهي: PostgreSQL، MySQL، MongoDB يا ٻيو ڪجهه (فائل، API، جيڪڏهن اوچتو ڪو مناسب لفافي نه آهي، توهان پنهنجو پاڻ لکي سگهو ٿا). خير، سڀڪنھن شيء کي شاندار لڳي! ڇا اسان ٽوڙي رهيا آهيون؟

جيڪڏهن سڀ ڪجهه ايترو جلدي ۽ سادو ختم ٿي ويو، پوء، شايد، اتي هڪ مضمون نه هوندو.

اهو واضح هجڻ ضروري آهي ته پوسٽ گريس ريموٽ سرورز جي درخواستن کي ڪيئن پروسيس ڪري ٿو. اهو منطقي لڳي ٿو، پر اڪثر ماڻهو ان تي ڌيان نه ڏيندا آهن: پوسٽ گريس درخواست کي حصن ۾ ورهائي ٿو جيڪي آزاد طور تي ريموٽ سرورز تي عمل ڪيا ويا آهن، هي ڊيٽا گڏ ڪري ٿو، ۽ حتمي حساب پاڻ کي انجام ڏئي ٿو، تنهن ڪري سوال جي عمل جي رفتار تي تمام گهڻو انحصار ڪندو. اهو ڪيئن لکيو ويو آهي. اهو پڻ نوٽ ڪيو وڃي ٿو: جڏهن ڊيٽا ريموٽ سرور کان اچي ٿي، ان کي هاڻي انڊيڪس نه آهي، اتي ڪجھ به نه آهي جيڪو شيڊولر جي مدد ڪندو، تنهن ڪري، صرف اسان پاڻ کي مدد ڪري سگهون ٿا ۽ هن کي مشورو ڏئي سگهون ٿا. ۽ اھو اھو آھي جيڪو آئون وڌيڪ تفصيل سان ڳالھائڻ چاھيان ٿو.

هڪ سادي سوال ۽ ان سان گڏ هڪ منصوبو

اهو ڏيکارڻ لاءِ ته پوسٽ گريس ريموٽ سرور تي 6 ملين قطار ٽيبل ڪيئن سوال ڪري ٿو، اچو ته هڪ سادي منصوبي تي نظر وجهون.

explain analyze verbose  
SELECT count(1)
FROM fdw_schema.table;

Aggregate  (cost=418383.23..418383.24 rows=1 width=8) (actual time=3857.198..3857.198 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.00..402376.14 rows=6402838 width=0) (actual time=4.874..3256.511 rows=6406868 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Remote SQL: SELECT NULL FROM fdw_schema.table
Planning time: 0.986 ms
Execution time: 3857.436 ms

VERBOSE بيان کي استعمال ڪندي اسان کي اهو سوال ڏسڻ جي اجازت ڏئي ٿو جيڪو ريموٽ سرور ڏانهن موڪليو ويندو ۽ جنهن جا نتيجا اسان کي وڌيڪ پروسيسنگ لاءِ حاصل ڪنداسين (RemoteSQL لائن).

اچو ته ٿورو اڳتي وڃو ۽ اسان جي درخواست ۾ ڪيترائي فلٽر شامل ڪريو: ھڪڙو لاء بوليان فيلڊ، هڪ واقعا مهر وقفي ۾ ۽ هڪ طرف jsonb.

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active is True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' 
AND CURRENT_DATE - INTERVAL '6 month'
AND meta->>'source' = 'test';

Aggregate  (cost=577487.69..577487.70 rows=1 width=8) (actual time=27473.818..25473.819 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.00..577469.21 rows=7390 width=0) (actual time=31.369..25372.466 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: (("table".is_active IS TRUE) AND (("table".meta ->> 'source'::text) = 'test'::text) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
        Rows Removed by Filter: 5046843
        Remote SQL: SELECT created_dt, is_active, meta FROM fdw_schema.table
Planning time: 0.665 ms
Execution time: 27474.118 ms

هي اهو آهي جتي اهو نقطو آهي جنهن تي توهان کي ڌيان ڏيڻ جي ضرورت آهي جڏهن سوال لکڻ ۾ ڪوڙ آهي. فلٽرز ريموٽ سرور ڏانهن منتقل نه ڪيا ويا، جنهن جو مطلب اهو آهي ته ان کي عمل ڪرڻ لاء، پوسٽ گريس سڀني 6 ملين قطارن کي ڪڍي ٿو ته پوء مقامي طور تي فلٽر ڪرڻ لاء (فلٽر قطار) ۽ مجموعي کي انجام ڏيو. ڪاميابي جي ڪنجي هڪ سوال لکڻ آهي ته جيئن فلٽر ريموٽ مشين ڏانهن منتقل ڪيا وڃن، ۽ اسان وصول ڪريون ۽ صرف ضروري قطارون گڏ ڪريون.

اهو ڪجهه booleanshit آهي

boolean شعبن سان سڀ ڪجھ سادو آهي. اصل درخواست ۾، مسئلو آپريٽر جي سبب هو is. جيڪڏھن توھان ان کي تبديل ڪريو =، پوء اسان ھيٺ ڏنل نتيجو حاصل ڪريون ٿا:

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active = True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' 
AND CURRENT_DATE - INTERVAL '6 month'
AND meta->>'source' = 'test';

Aggregate  (cost=508010.14..508010.15 rows=1 width=8) (actual time=19064.314..19064.314 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.00..507988.44 rows=8679 width=0) (actual time=33.035..18951.278 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: ((("table".meta ->> 'source'::text) = 'test'::text) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
        Rows Removed by Filter: 3567989
        Remote SQL: SELECT created_dt, meta FROM fdw_schema.table WHERE (is_active)
Planning time: 0.834 ms
Execution time: 19064.534 ms

جئين توهان ڏسي سگهو ٿا، فلٽر ريموٽ سرور ڏانهن ڀڄي ويو، ۽ عمل جو وقت 27 کان 19 سيڪنڊن تائين گھٽجي ويو.

اهو قابل ذڪر آهي ته آپريٽر is آپريٽر کان مختلف = ڇاڪاڻ ته اهو Null قدر سان ڪم ڪري سگهي ٿو. ان جو مطلب آهي سچ نه آهي فلٽر ۾ False ۽ Null ويلز کي ڇڏي ڏيندو، جڏهن ته ! = سچ صرف غلط قدر ڇڏي ويندا. تنهن ڪري، جڏهن آپريٽر کي تبديل ڪيو وڃي نه آهي OR آپريٽر سان ٻه حالتون فلٽر ڏانهن منتقل ٿيڻ گهرجن، مثال طور، ڪٿي (col != سچو) يا (col null آهي).

اسان بولن سان معاملو ڪيو آهي، اچو ته اڳتي وڌون. ھاڻي، اچو ته بولن فلٽر کي ان جي اصل شڪل ڏانھن موٽون، آزاديء سان ٻين تبديلين جي اثر تي غور ڪرڻ لاء.

timestamptz؟ hz

عام طور تي، توهان کي اڪثر تجربو ڪرڻو پوندو آهي ته ڪيئن صحيح طريقي سان هڪ درخواست لکجي جنهن ۾ ريموٽ سرور شامل آهن، ۽ صرف پوءِ وضاحت ڳوليو ته ائين ڇو ٿئي ٿو. ان بابت تمام گهٽ معلومات انٽرنيٽ تي ملي سگهي ٿي. تنهن ڪري، تجربن ۾ اسان ڏٺو ته هڪ مقرر ٿيل تاريخ فلٽر هڪ ڌماڪي سان ريموٽ سرور ڏانهن اڏامي ٿو، پر جڏهن اسان تاريخ کي متحرڪ طور تي مقرر ڪرڻ چاهيون ٿا، مثال طور، هاڻي() يا CURRENT_DATE، ائين نٿو ٿئي. اسان جي مثال ۾، اسان هڪ فلٽر شامل ڪيو آهي ته جيئن ٺاهيل_at ڪالمن ۾ ڊيٽا شامل آهي بلڪل 1 مهيني جي ماضي ۾ (BETWEEN CURRENT_DATE - INTERVAL '7 مهينا' ۽ CURRENT_DATE - INTERVAL '6 مهينا'). اسان هن معاملي ۾ ڇا ڪيو؟

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active is True
AND created_dt >= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month') 
AND created_dt <(SELECT CURRENT_DATE::timestamptz - INTERVAL '6 month')
AND meta->>'source' = 'test';

Aggregate  (cost=306875.17..306875.18 rows=1 width=8) (actual time=4789.114..4789.115 rows=1 loops=1)
  Output: count(1)
  InitPlan 1 (returns $0)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.007..0.008 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)
  InitPlan 2 (returns $1)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.002..0.002 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.02..306874.86 rows=105 width=0) (actual time=23.475..4681.419 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: (("table".is_active IS TRUE) AND (("table".meta ->> 'source'::text) = 'test'::text))
        Rows Removed by Filter: 76934
        Remote SQL: SELECT is_active, meta FROM fdw_schema.table WHERE ((created_dt >= $1::timestamp with time zone)) AND ((created_dt < $2::timestamp with time zone))
Planning time: 0.703 ms
Execution time: 4789.379 ms

اسان پلانر کي چيو ته ذيلي پڇا ڳاڇا ۾ تاريخ کي اڳ ۾ ڳڻيو ۽ فلٽر ۾ تيار ٿيل ويريبل پاس ڪريو. ۽ هي اشارو اسان کي هڪ بهترين نتيجو ڏنو، درخواست تقريبا 6 ڀيرا تيز ٿي وئي!

ٻيهر، هتي احتياط ڪرڻ ضروري آهي: ذيلي پڇاڙيء ۾ ڊيٽا جو قسم ساڳيو هجڻ گهرجي انهي فيلڊ جي جنهن تي اسين فلٽر ڪري رهيا آهيون، ٻي صورت ۾ پلانر فيصلو ڪندو ته جيئن ته قسم مختلف آهن، اهو ضروري آهي ته سڀ کان پهريان سڀني کي حاصل ڪيو وڃي. ڊيٽا کي فلٽر ڪريو ۽ مقامي طور تي فلٽر ڪريو.

اچو ته تاريخ جي فلٽر کي ان جي اصل قيمت ڏانھن موٽائي.

فريدي بمقابلہ فريدي جيسنب

عام طور تي، Boolean شعبن ۽ تاريخن اڳ ۾ ئي اسان جي سوال کي تيز ڪري ڇڏيو آهي، پر هڪ وڌيڪ ڊيٽا جو قسم باقي هو. ان جي ذريعي فلٽر ڪرڻ سان جنگ، ايماندار هجڻ، اڃا به ختم نه ٿيو آهي، جيتوڻيڪ هتي ڪاميابي پڻ آهي. تنهن ڪري، هن طريقي سان اسان فلٽر کي پاس ڪرڻ جو انتظام ڪيو jsonb فيلڊ ريموٽ سرور ڏانهن.

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active is True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' 
AND CURRENT_DATE - INTERVAL '6 month'
AND meta @> '{"source":"test"}'::jsonb;

Aggregate  (cost=245463.60..245463.61 rows=1 width=8) (actual time=6727.589..6727.590 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=1100.00..245459.90 rows=1478 width=0) (actual time=16.213..6634.794 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: (("table".is_active IS TRUE) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
        Rows Removed by Filter: 619961
        Remote SQL: SELECT created_dt, is_active FROM fdw_schema.table WHERE ((meta @> '{"source": "test"}'::jsonb))
Planning time: 0.747 ms
Execution time: 6727.815 ms

فلٽرنگ آپريٽرز جي بدران، توهان کي هڪ آپريٽر جي موجودگي کي استعمال ڪرڻ گهرجي jsonb هڪ مختلف ۾. اصل 7 جي بدران 29 سيڪنڊ. هينئر تائين اهو ئي واحد ڪامياب آپشن آهي جيڪو فلٽر ذريعي منتقل ڪرڻ لاءِ jsonb هڪ ريموٽ سرور ڏانهن، پر هتي اهو ضروري آهي ته هڪ حد کي نظر ۾ رکڻ گهرجي: اسان ڊيٽابيس جو نسخو 9.6 استعمال ڪري رهيا آهيون، پر اپريل جي آخر تائين اسان آخري ٽيسٽ مڪمل ڪرڻ ۽ ورزن 12 ڏانهن منتقل ڪرڻ جو ارادو ڪيو. هڪ دفعو اسان تازه ڪاري ڪنداسين، اسان ان بابت لکنداسين ته اهو ڪيئن متاثر ٿيو، ڇاڪاڻ ته اتي ڪافي تبديليون آهن جن لاءِ تمام گهڻي اميد آهي: json_path، نئون CTE رويي، push down (موجوده نسخو 10 کان). مان واقعي جلدي ڪوشش ڪرڻ چاهيان ٿو.

هن کي ختم ڪريو

اسان جانچيو ته هر تبديلي انفرادي طور تي درخواست جي رفتار کي ڪيئن متاثر ڪيو. اچو ته هاڻي ڏسون ته ڇا ٿيندو جڏهن سڀ ٽي فلٽر صحيح لکيا وڃن.

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active = True
AND created_dt >= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month') 
AND created_dt <(SELECT CURRENT_DATE::timestamptz - INTERVAL '6 month')
AND meta @> '{"source":"test"}'::jsonb;

Aggregate  (cost=322041.51..322041.52 rows=1 width=8) (actual time=2278.867..2278.867 rows=1 loops=1)
  Output: count(1)
  InitPlan 1 (returns $0)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.010..0.010 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)
  InitPlan 2 (returns $1)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.02..322041.41 rows=25 width=0) (actual time=8.597..2153.809 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Remote SQL: SELECT NULL FROM fdw_schema.table WHERE (is_active) AND ((created_dt >= $1::timestamp with time zone)) AND ((created_dt < $2::timestamp with time zone)) AND ((meta @> '{"source": "test"}'::jsonb))
Planning time: 0.820 ms
Execution time: 2279.087 ms

ها، درخواست وڌيڪ پيچيده لڳي ٿي، اها زبردستي فيس آهي، پر عملدرآمد جي رفتار 2 سيڪنڊ آهي، جيڪا 10 ڀيرا وڌيڪ تيز آهي! ۽ اسان هڪ نسبتا ننڍڙي ڊيٽا سيٽ جي خلاف هڪ سادي سوال بابت ڳالهائي رهيا آهيون. حقيقي درخواستن تي، اسان کي ڪيترن ئي سؤ ڀيرا اضافو مليو.

اختصار ڪرڻ لاءِ: جيڪڏهن توهان FDW سان PostgreSQL استعمال ڪريو ٿا، هميشه چيڪ ڪريو ته سڀئي فلٽر ريموٽ سرور ڏانهن موڪليا ويا آهن، ۽ توهان خوش ٿيندا... گهٽ ۾ گهٽ جيستائين توهان مختلف سرورن جي ٽيبلن جي وچ ۾ شامل ٿيڻ تائين پهچي نه وڃو. پر اهو هڪ ٻئي مضمون لاء هڪ ڪهاڻي آهي.

توهان جي توجه لاء مهرباني! مان تبصرن ۾ توهان جي تجربن بابت سوال، تبصرا، ۽ ڳالهيون ٻڌڻ چاهيان ٿو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو