በማይክሮ ሰርቪስ አርክቴክቸር ውስጥ ተግባራዊ ትንታኔ፡ የፖስትግሬስ FDW እገዛ እና መጠየቂያ

የማይክሮ ሰርቪስ አርክቴክቸር፣ ልክ በዚህ አለም ውስጥ እንዳለ ሁሉ፣ ጥቅሞቹ እና ጉዳቶቹ አሉት። አንዳንድ ሂደቶች በእሱ ቀላል ይሆናሉ, ሌሎች ደግሞ ይበልጥ አስቸጋሪ ይሆናሉ. እና ለለውጥ ፍጥነት እና ለተሻለ መጠነ-ሰፊነት, መስዋዕትነትን መክፈል ያስፈልግዎታል. ከመካከላቸው አንዱ የትንታኔ ውስብስብነት ነው። በአንድ ሞኖሊት ውስጥ ሁሉም የአሠራር ትንታኔዎች ወደ SQL መጠይቆች ወደ የትንታኔ ቅጂ ሊቀነስ ከቻሉ፣ በባለብዙ አገልግሎት አርክቴክቸር ውስጥ እያንዳንዱ አገልግሎት የራሱ ዳታቤዝ አለው እና አንድ መጠይቅ በቂ አይደለም (ወይንስ ሊሆን ይችላል?) ይመስላል። በእኛ ኩባንያ ውስጥ ያለውን የአሠራር ትንተና ችግር እንዴት እንደፈታን እና ከዚህ መፍትሄ ጋር እንዴት መኖር እንደተማርን ፍላጎት ላላቸው - እንኳን ደህና መጡ።

በማይክሮ ሰርቪስ አርክቴክቸር ውስጥ ተግባራዊ ትንታኔ፡ የፖስትግሬስ FDW እገዛ እና መጠየቂያ
ስሜ ፓቬል ሲቫሽ እባላለሁ DomClick ላይ የትንታኔ መረጃ ማከማቻውን የመጠበቅ ሃላፊነት ባለው ቡድን ውስጥ እሰራለሁ። በተለምዶ፣ የእኛ ተግባራቶች በመረጃ ምህንድስና ምክንያት ሊወሰዱ ይችላሉ፣ ነገር ግን፣ በእውነቱ፣ የተግባር ወሰን በጣም ሰፊ ነው። መደበኛ የመረጃ ምህንድስና ETL / ELT ፣ የመረጃ ትንተና መሣሪያዎች ድጋፍ እና መላመድ እና የእራሳቸውን መሳሪያዎች ልማት አሉ። በተለይ ለኦፕሬሽን ዘገባዎች ሞኖሊት እንዳለን "ለመምሰል" እና ተንታኞች የሚያስፈልጋቸውን ሁሉንም መረጃዎች የሚይዝ አንድ የመረጃ ቋት ለመስጠት ወስነናል።

በአጠቃላይ የተለያዩ አማራጮችን ተመልክተናል. የተሟላ የመረጃ ቋት መገንባት ተችሏል - እኛ እንኳን ሞክረን ነበር ፣ ግን እውነቱን ለመናገር ፣ ክምችት በመገንባት እና በእሱ ላይ ለውጦችን በማድረግ በሎጂክ ውስጥ በትክክል ተደጋጋሚ ለውጦች ጋር ጓደኛ ማፍራት አልቻልንም ነበር ( አንድ ሰው ከተሳካ, እንዴት በአስተያየቶቹ ውስጥ ይፃፉ). ተንታኞችን እንዲህ ማለት ትችላለህ፡- “ጓዶች፣ python ተማሩ እና ወደ የትንታኔ መስመሮች ሂዱ”፣ ግን ይህ ተጨማሪ የምልመላ መስፈርት ነው፣ እና ከተቻለ ይህ መወገድ ያለበት ይመስላል። እኛ የ FDW (የውጭ መረጃ መጠቅለያ) ቴክኖሎጂን ለመጠቀም ለመሞከር ወስነናል፡ በእርግጥ ይህ መደበኛ dblink ነው፣ እሱም በ SQL መስፈርት ውስጥ ነው፣ ግን በጣም ምቹ በሆነ በይነገጽ። በዚህ መሠረት አንድ ውሳኔ ወስነናል, በመጨረሻም ሥር ሰድደናል, በእሱ ላይ ተስማማን. ዝርዝሮቹ የአንድ የተለየ ጽሑፍ ርዕስ እና ምናልባትም ከአንድ በላይ ናቸው, ምክንያቱም ስለ ብዙ ማውራት ስለምፈልግ ከመረጃ ቋት ንድፍ ማመሳሰል እስከ ቁጥጥር እና የግል ውሂብን ማግለል. በተጨማሪም ይህ መፍትሔ ለትክክለኛው የትንታኔ የውሂብ ጎታዎች እና ማከማቻዎች ምትክ እንዳልሆነ ልብ ሊባል ይገባል, አንድ የተወሰነ ችግር ብቻ ይፈታል.

በከፍተኛ ደረጃ ላይ እንደዚህ ይመስላል:

በማይክሮ ሰርቪስ አርክቴክቸር ውስጥ ተግባራዊ ትንታኔ፡ የፖስትግሬስ FDW እገዛ እና መጠየቂያ
ተጠቃሚዎች የስራ ውሂባቸውን የሚያከማቹበት የ PostgreSQL ዳታቤዝ አለ፣ እና ከሁሉም በላይ የሁሉም አገልግሎቶች የትንታኔ ቅጂዎች ከዚህ ዳታቤዝ ጋር በFDW በኩል የተገናኙ ናቸው። ይህ ጥያቄን ወደ በርካታ የውሂብ ጎታዎች ለመጻፍ ያስችለዋል, እና ምንም ለውጥ አያመጣም: PostgreSQL, MySQL, MongoDB ወይም ሌላ ነገር (ፋይል, ኤፒአይ, በድንገት ምንም ተስማሚ መጠቅለያ ከሌለ, የራስዎን መጻፍ ይችላሉ). ደህና ፣ ሁሉም ነገር ጥሩ ይመስላል! መለያየት?

ሁሉም ነገር በፍጥነት እና በቀላሉ ከተጠናቀቀ, ምናልባት, ጽሑፉ ላይኖር ይችላል.

ፖስትግሬስ የርቀት አገልጋዮችን እንዴት እንደሚይዝ ግልጽ ማድረግ አስፈላጊ ነው. ይህ ምክንያታዊ ይመስላል, ነገር ግን ብዙውን ጊዜ ሰዎች ትኩረት አይሰጡትም: ፖስትግሬስ መጠይቁን በሩቅ አገልጋዮች ላይ በተናጥል ወደሚፈጸሙ ክፍሎች ይከፍላል, ይህንን መረጃ ይሰበስባል እና የመጨረሻውን ስሌት እራሱ ያከናውናል, ስለዚህ የጥያቄው አፈፃፀም ፍጥነት እንዴት ላይ በእጅጉ ይወሰናል. ተብሎ ተጽፏል። በተጨማሪም መታወቅ ያለበት: መረጃው ከርቀት አገልጋይ ሲመጣ, ከአሁን በኋላ ኢንዴክሶች የላቸውም, የጊዜ ሰሌዳውን የሚረዳ ምንም ነገር የለም, ስለዚህ እኛ እራሳችን ብቻ መርዳት እና መጠቆም እንችላለን. እና ስለዚያ ነው የበለጠ በዝርዝር መናገር የምፈልገው።

ቀላል ጥያቄ እና እቅድ ከእሱ ጋር

Postgres እንዴት በሩቅ አገልጋይ ላይ ባለ 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 string) እንዲያዩ ያስችልዎታል።

ትንሽ ወደ ፊት እንሂድ እና ብዙ ማጣሪያዎችን ወደ ጥያቄያችን እንጨምር፡ አንድ በአንድ ቡሊያን መስክ, አንድ በመግቢያው ማህተም በእያንዳንዱ ክፍተት እና አንድ በአንድ 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 ሚሊዮን ረድፎችን ይጎትታል (የማጣሪያ መስመር) እና በኋላ ላይ ድምርን ያካሂዳል። ለስኬት ቁልፉ ጥያቄን መፃፍ ነው ማጣሪያዎቹ ወደ የርቀት ማሽኑ እንዲተላለፉ እና አስፈላጊዎቹን ረድፎች ብቻ እንቀበላለን እና እንሰበስባለን ።

ያ አንዳንድ ቡሊያንሺት ነው።

በቦሊያን ሜዳዎች ሁሉም ነገር ቀላል ነው. በዋናው መጠይቅ ችግሩ የተፈጠረው በኦፕሬተሩ ነው። 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 ከኦፕሬተር የተለየ = ከኑል እሴት ጋር መሥራት የሚችለው። ማለት ነው። እውነት አይደለም በማጣሪያው ውስጥ እሴቶቹን ሐሰት እና ባዶ ይተዋል ፣ ግን != እውነት ነው። የውሸት እሴቶችን ብቻ ይተዋል. ስለዚህ, ኦፕሬተሩን ሲተካ አይደለም ከ OR ኦፕሬተር ጋር ሁለት ሁኔታዎችን ወደ ማጣሪያው ማለፍ አለብዎት ፣ ለምሳሌ ፣ የት (col! = እውነት) ወይም (ኮል ባዶ ነው).

ቡሊያን በማወቅ፣ ወደፊት ቀጥል። እስከዚያው ድረስ፣ የሌሎች ለውጦችን ውጤት በግል ለማየት ማጣሪያውን በቦሊያን እሴት ወደ መጀመሪያው መልክ እንመልሰው።

timestamptz? hz

በአጠቃላይ፣ ብዙ ጊዜ የርቀት አገልጋዮችን የሚያካትት ጥያቄ እንዴት በትክክል እንደሚፃፍ መሞከር አለቦት፣ እና ከዚያ በኋላ ይህ ለምን እየሆነ እንደሆነ ማብራሪያ ይፈልጉ። ስለዚህ ጉዳይ በጣም ትንሽ መረጃ በኢንተርኔት ላይ ሊገኝ ይችላል. ስለዚህ፣ በሙከራዎች ውስጥ፣ ቋሚ የቀን ማጣሪያ ባንግ ወዳለው የርቀት አገልጋይ እንደሚበር ደርሰንበታል፣ነገር ግን ቀኑን በተለዋዋጭ ሁኔታ ለማዘጋጀት ስንፈልግ፣ለምሳሌ አሁን() ወይም CURRENT_DATE፣ ይህ አይከሰትም። በእኛ ምሳሌ ውስጥ፣ የተፈጠረው_አምድ አምድ ላለፈው በትክክል ለ1 ወር ያህል ውሂብ እንዲይዝ ማጣሪያ አክለናል (በCURRENT_DATE - INTERVAL '7 month' AND CURRENT_DATE - INTERVAL '6 month')። በዚህ ጉዳይ ላይ ምን አደረግን?

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 ጊዜ ያህል ፈጣን ሆነ!

በድጋሚ, እዚህ ላይ ጥንቃቄ ማድረግ አስፈላጊ ነው-በንዑስ መጠይቁ ውስጥ ያለው የውሂብ አይነት እኛ ከምንጣራበት መስክ ጋር ተመሳሳይ መሆን አለበት, አለበለዚያ እቅድ አውጪው የሚወስነው አይነቶቹ የተለያዩ ስለሆኑ እና በመጀመሪያ ሁሉንም ማግኘት አስፈላጊ ነው. ውሂብ እና በአካባቢው ያጣሩ.

ማጣሪያውን በቀን ወደ መጀመሪያው እሴቱ እንመልሰው።

ፍሬዲ vs. jsonb

በአጠቃላይ፣ የቦሊያን መስኮች እና ቀኖች ጥያቄያችንን በበቂ ሁኔታ አፋጥነዋል፣ ነገር ግን አንድ ተጨማሪ የውሂብ አይነት ነበር። በእሱ የማጣራት ውጊያ፣ እውነቱን ለመናገር፣ አሁንም አላበቃም፣ ምንም እንኳን እዚህም ስኬቶች አሉ። ስለዚህ ማጣሪያውን እንዴት ማለፍ እንደቻልን እነሆ 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 ባህሪ፣ ወደ ታች ይግፉ (ከስሪት 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 እጥፍ በላይ ፈጣን ነው! እና በአንጻራዊነት ትንሽ የውሂብ ስብስብ ላይ ስለ ቀላል መጠይቅ እየተነጋገርን ነው. በእውነተኛ ጥያቄዎች ላይ እስከ ብዙ መቶ እጥፍ ጭማሪ አግኝተናል።

ለማጠቃለል፡- PostgreSQLን ከ FDW ጋር እየተጠቀሙ ከሆነ ሁል ጊዜ ሁሉም ማጣሪያዎች ወደ የርቀት አገልጋዩ የተላኩ መሆናቸውን ያረጋግጡ እና ደስተኛ ይሆናሉ ... ቢያንስ ከተለያዩ ሰርቨሮች በጠረጴዛዎች መካከል መቀላቀል እስኪያገኙ ድረስ። ግን ይህ ለሌላ መጣጥፍ ታሪክ ነው።

ለሰጠህው አትኩሮት እናመሰግናለን! በአስተያየቶቹ ውስጥ ስለ እርስዎ ተሞክሮ ጥያቄዎችን ፣ አስተያየቶችን እና ታሪኮችን መስማት እፈልጋለሁ።

ምንጭ: hab.com

አስተያየት ያክሉ