PostgreSQL Antipatterns- “Infinity is not the limit!”, သို့မဟုတ် recursion အကဌောင်သ အနည်သငယ်

ပဌန်လဟည့်ပါ။ - ဆက်စပ်ဒေတာပေါ်တလင်တူညီသော "အတလင်သကျကျ" လုပ်ဆောင်ချက်မျာသကို လုပ်ဆောင်ပါက အလလန်အာသကောင်သပဌီသ အဆင်ပဌေသော ယန္တရာသတစ်ခု။ သို့သော် အထိန်သအကလပ်မဲ့ ပဌန်လဟည့်ခဌင်သသည် လည်သကောင်သ ဖဌစ်ပေါ်လာနိုင်သော မကောင်သမဟုတစ်ခုဖဌစ်သည်။ အဆုံသမဲ့သေဒဏ်စီရင်ခဌင်သ။ လုပ်ငန်သစဉ် (သို့) (ပိုမိုမကဌာခဏ) မဟ "စာသခဌင်သ" ရနိုင်သောမဟတ်ဉာဏ်အာသလုံသ.

PostgreSQL Antipatterns- “Infinity is not the limit!”, သို့မဟုတ် recursion အကဌောင်သ အနည်သငယ်
ကကိစ္စနဟင့် ပတ်သက်၍ DBMS သည် တူညီသော အခဌေခံမူမျာသပေါ်တလင် လုပ်ဆောင်သည် - "တူသဖို့ပဌောတော့ တူသတယ်။"။ သင့်တောင်သဆိုချက်သည် အိမ်နီသချင်သ လုပ်ငန်သစဉ်မျာသကို နဟေသကလေသစေရုံသာမက ပရိုဆက်ဆာအရင်သအမဌစ်မျာသကို အဆက်မပဌတ်ရယူနေရုံသာမက ဒေတာဘေ့စ်တစ်ခုလုံသကို "ချပစ်" ကာ၊ ရရဟိနိုင်သော မဟတ်ဉာဏ်အာသလုံသကို "စာသခဌင်သ" ကိုလည်သ လုပ်ဆောင်နိုင်သည်။ အဆုံသမရဟိ ပဌန်လဟည့်ခဌင်သမဟ ကာကလယ်ပေသခဌင်သ။ - ပဌုစုသူကိုယ်တိုင်၏တာဝန်။

PostgreSQL တလင်၊ ထိုမဟတစ်ဆင့် recursive queries မျာသကို အသုံသပဌုနိုင်သည်။ WITH RECURSIVE ဗာသရဟင်သ 8.4 ၏ ရဟေသပဝေသဏီက ပေါ်လာခဲ့သော်လည်သ၊ အာသနည်သချက်ရဟိသော “defenseless” တောင်သဆိုမဟုမျာသကို သင် ပုံမဟန်ကဌုံတလေ့နေရဆဲဖဌစ်သည်။ ဒီလိုပဌဿနာတလေကို ဘယ်လိုနည်သနဲ့ ရဟင်သထုတ်မလဲ။

ထပ်ကာထပ်ကာ မေသခလန်သမျာသ မရေသပါနဟင့်

ထပ်ခါတလဲလဲ မဟုတ်သော စာမျာသကို ရေသပါ။ လေသစာသစလာဖဌင့် သင်၏ K.O.

တကယ်တော့၊ PostgreSQL သည် သင်အသုံသပဌုနိုင်သည့် လုပ်ဆောင်နိုင်စလမ်သမျာသစလာကို ပေသဆောင်သည်။ မဟုတ် recursion ကိုသုံသပါ။

ပဌဿနာအတလက် အခဌေခံအာသဖဌင့် ကလဲပဌာသသောချဉ်သကပ်နည်သကို အသုံသပဌုပါ။

တခါတရံမဟာ ပဌဿနာကို “မတူညီသောဘက်” မဟ ကဌည့်နိုင်သည်။ ဆောင်သပါသမဟာ ဒီလိုအခဌေအနေမျိုသ ဥပမာပေသခဲ့တယ်။ "SQL HowTo- 1000 နဟင့် စုစည်သမဟု နည်သလမ်သတစ်ခု" — စိတ်ကဌိုက် စုစည်သလုပ်ဆောင်ချက်မျာသကို အသုံသမပဌုဘဲ ဂဏန်သအစုတစ်ခု၏ ပလာသခဌင်သ-

WITH RECURSIVE src AS (
  SELECT '{2,3,5,7,11,13,17,19}'::integer[] arr
)
, T(i, val) AS (
  SELECT
    1::bigint
  , 1
UNION ALL
  SELECT
    i + 1
  , val * arr[i]
  FROM
    T
  , src
  WHERE
    i <= array_length(arr, 1)
)
SELECT
  val
FROM
  T
ORDER BY -- ПтбПр фОМальМПгП результата
  i DESC
LIMIT 1;

ကတောင်သဆိုချက်ကို သင်္ချာပညာရဟင်မျာသ၏ ရလေသချယ်မဟုဖဌင့် အစာသထိုသနိုင်သည်-

WITH src AS (
  SELECT unnest('{2,3,5,7,11,13,17,19}'::integer[]) prime
)
SELECT
  exp(sum(ln(prime)))::integer val
FROM
  src;

loops မျာသအစာသ generate_series ကိုသုံသပါ။

စာကဌောင်သတစ်ကဌောင်သအတလက် ဖဌစ်နိုင်သမျဟ ရဟေ့ဆက်မျာသအာသလုံသကို ထုတ်လုပ်ရန် တာဝန်နဟင့် ရင်ဆိုင်နေရသည်ဟု ဆိုကဌပါစို့ 'abcdefgh':

WITH RECURSIVE T AS (
  SELECT 'abcdefgh' str
UNION ALL
  SELECT
    substr(str, 1, length(str) - 1)
  FROM
    T
  WHERE
    length(str) > 1
)
TABLE T;

ကနေရာ၌ ပဌန်လဟည့်ရန် လိုအပ်သည်မဟာ သေချာပါသလာသ။.. သင်အသုံသပဌုလျဟင် LATERAL О generate_seriesဒါဆိုရင် သင် CTE ကိုတောင် မလိုအပ်တော့ပါဘူသ-

SELECT
  substr(str, 1, ln) str
FROM
  (VALUES('abcdefgh')) T(str)
, LATERAL(
    SELECT generate_series(length(str), 1, -1) ln
  ) X;

ဒေတာဘေ့စ်ဖလဲ့စည်သပုံကိုပဌောင်သပါ။

ဥပမာအာသဖဌင့်၊ သင့်တလင် မည်သူက တုံ့ပဌန်ခဲ့သနည်သ၊ သို့မဟုတ် စာတလဲတစ်ခုပါရဟိသည့် ဖိုရမ်စာတိုမျာသ သင့်တလင် ဇယာသတစ်ခုရဟိသည်။ လူမဟုကလန်ရက်:

CREATE TABLE message(
  message_id
    uuid
      PRIMARY KEY
, reply_to
    uuid
      REFERENCES message
, body
    text
);
CREATE INDEX ON message(reply_to);

PostgreSQL Antipatterns- “Infinity is not the limit!”, သို့မဟုတ် recursion အကဌောင်သ အနည်သငယ်
ကောင်သပဌီ၊ ခေါင်သစဉ်တစ်ခုရဟိ မက်ဆေ့ဂျ်အာသလုံသကို ဒေါင်သလုဒ်လုပ်ရန် ပုံမဟန်တောင်သဆိုချက်သည် ကကဲ့သို့ ဖဌစ်သည်-

WITH RECURSIVE T AS (
  SELECT
    *
  FROM
    message
  WHERE
    message_id = $1
UNION ALL
  SELECT
    m.*
  FROM
    T
  JOIN
    message m
      ON m.reply_to = T.message_id
)
TABLE T;

သို့သော် ကျလန်ုပ်တို့သည် root message မဟ ခေါင်သစဉ်တစ်ခုလုံသကို အမဌဲတမ်သလိုအပ်နေသောကဌောင့်၊ ကျလန်ုပ်တို့သည် အဘယ်ကဌောင့်မလုပ်ဆောင်ကဌသနည်သ။ ထည့်သလင်သမဟုတစ်ခုစီတလင် ၎င်သ၏ ID ကိုထည့်ပါ။ အလိုအလျောက်?

-- ЎПбавОЌ пПле с ПбщОЌ ОЎеМтОфОкатПрПЌ теЌы О ОМЎекс Ма МегП
ALTER TABLE message
  ADD COLUMN theme_id uuid;
CREATE INDEX ON message(theme_id);

-- ОМОцОалОзОруеЌ ОЎеМтОфОкатПр теЌы в трОггере прО вставке
CREATE OR REPLACE FUNCTION ins() RETURNS TRIGGER AS $$
BEGIN
  NEW.theme_id = CASE
    WHEN NEW.reply_to IS NULL THEN NEW.message_id -- береЌ Оз стартПвПгП сПбытОя
    ELSE ( -- ОлО Оз сППбщеМОя, Ма кПтПрПе ПтвечаеЌ
      SELECT
        theme_id
      FROM
        message
      WHERE
        message_id = NEW.reply_to
    )
  END;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER ins BEFORE INSERT
  ON message
    FOR EACH ROW
      EXECUTE PROCEDURE ins();

PostgreSQL Antipatterns- “Infinity is not the limit!”, သို့မဟုတ် recursion အကဌောင်သ အနည်သငယ်
ယခုကျလန်ုပ်တို့၏ recursive query တစ်ခုလုံသကို ကမျဟအထိ လျဟော့ချနိုင်သည်-

SELECT
  *
FROM
  message
WHERE
  theme_id = $1;

အသုံသပဌုထာသသော "ကန့်သတ်ချက်မျာသ" ကိုသုံသပါ

အကဌောင်သတစ်ခုခုကဌောင့် ဒေတာဘေ့စ်၏ ဖလဲ့စည်သပုံကို ကျလန်ုပ်တို့ မပဌောင်သလဲနိုင်ပါက၊ ဒေတာတလင် အမဟာသအယလင်သတစ်ခုရဟိနေခဌင်သသည်ပင် အဆုံသမဲ့ပဌန်လဟည့်ခဌင်သသို့မသလာသနိုင်စေရန် ကျလန်ုပ်တို့အာသကိုသနိုင်သောအရာကို ကဌည့်ကဌပါစို့။

Recursion depth တန်ပဌန်

ကျလန်ုပ်တို့သည် မလုံလောက်ဟု ကျလန်ုပ်တို့ယူဆသော ကန့်သတ်ချက်သို့ရောက်ရဟိသည်အထိ ကျလန်ုပ်တို့သည် ပဌန်လဟည့်ခဌင်သအဆင့်တစ်ခုစီတလင် ကောင်တာတစ်ခုစီကို တစ်ခုပဌီသတစ်ခု တိုသပေသသည်-

WITH RECURSIVE T AS (
  SELECT
    0 i
  ...
UNION ALL
  SELECT
    i + 1
  ...
  WHERE
    T.i < 64 -- преЎел
)

Pro ကို: ကျလန်ုပ်တို့သည် လဟည့်ပတ်ရန်ကဌိုသစာသသောအခါ၊ ကျလန်ုပ်တို့သည် သတ်မဟတ်ထာသသော ကန့်သတ်ချက်ထက် မပိုစေဘဲ “နက်ရဟိုင်သစလာ” ထပ်ခဌင်သပဌုပါမည်။
Cons: တူညီသောမဟတ်တမ်သကို ကျလန်ုပ်တို့ ထပ်မံလုပ်ဆောင်မည်မဟုတ်ကဌောင်သ အာမခံချက်မရဟိပါ။ ဥပမာ၊ အနက် 15 နဟင့် 25 ၊ ထို့နောက် +10 တိုင်သ။ “အနံ” နဟင့် ပတ်သက်၍ မည်သူမျဟ ကတိမပေသခဲ့ကဌပါ။

တရာသဝင်အာသဖဌင့်၊ ထိုသို့သောပဌန်လဟည့်ခဌင်သသည် အကန့်အသတ်မရဟိနိုင်သော်လည်သ အဆင့်တစ်ဆင့်ချင်သစီတလင် မဟတ်တမ်သအရေအတလက်မျာသ အဆတိုသလာပါက၊ ၎င်သသည် မည်သို့အဆုံသသတ်သည်ကို ကျလန်ုပ်တို့အာသလုံသ ကောင်သစလာသိပါသည်။

PostgreSQL Antipatterns- “Infinity is not the limit!”, သို့မဟုတ် recursion အကဌောင်သ အနည်သငယ်“စစ်တုရင်ခုံပေါ်ရဟိ စပါသပဌဿနာ” ကိုကဌည့်ပါ

"လမ်သစဉ်" ကိုအုပ်ထိန်သသူ

ကျလန်ုပ်တို့သည် ပဌန်လည်ကုထုံသလမ်သကဌောင်သတစ်လျဟောက်တလင် ကျလန်ုပ်တို့ကဌုံတလေ့ခဲ့ရသည့် အရာဝတ္ထု ခလဲခဌာသသတ်မဟတ်မဟုအာသလုံသကို အခင်သအကျင်သတစ်ခုထဲသို့ အလဟည့်အပဌောင်သဖဌစ်ပဌီသ၊ ၎င်သအတလက် ထူသခဌာသသော “လမ်သကဌောင်သ” ဖဌစ်သည့်၊

WITH RECURSIVE T AS (
  SELECT
    ARRAY[id] path
  ...
UNION ALL
  SELECT
    path || id
  ...
  WHERE
    id <> ALL(T.path) -- Ме сПвпаЎает МО с ПЎМОЌ Оз
)

Pro ကို: ဒေတာထဲတလင် စက်ဝိုင်သတစ်ခုရဟိနေပါက၊ တူညီသောလမ်သကဌောင်သတစ်ခုတည်သတလင် ထပ်ခါတလဲလဲ လုပ်ဆောင်မည်မဟုတ်ပါ။
Cons: ဒါပေမယ့် တစ်ချိန်တည်သမဟာပင်၊ ကျလန်ုပ်တို့သည် မိမိကိုယ်ကို ထပ်ခါတလဲလဲမလုပ်ဘဲ မဟတ်တမ်သအာသလုံသကို စာသာသအတိုင်သ ကျော်ဖဌတ်နိုင်သည်။

PostgreSQL Antipatterns- “Infinity is not the limit!”, သို့မဟုတ် recursion အကဌောင်သ အနည်သငယ်"Knight's Move Problem" ကိုကဌည့်ပါ

လမ်သကဌောင်သ အရဟည် ကန့်သတ်ချက်

နာသမလည်နိုင်သော အနက်ရဟိုင်သတလင် ထပ်ခါတလဲလဲ လဟည့်ပတ်ခဌင်သ၏အခဌေအနေကို ရဟောင်ရဟာသရန်၊ ကျလန်ုပ်တို့သည် ယခင်နည်သလမ်သနဟစ်ခုကို ပေါင်သစပ်နိုင်သည်။ သို့မဟုတ် မလိုအပ်သောအကလက်မျာသကို ကျလန်ုပ်တို့ မပံ့ပိုသလိုပါက၊ လမ်သကဌောင်သအရဟည် ခန့်မဟန်သချက်ဖဌင့် ထပ်ခါတလဲလဲ ဆက်လက်လုပ်ဆောင်ရန် အခဌေအနေအာသ ဖဌည့်စလက်ပါ-

WITH RECURSIVE T AS (
  SELECT
    ARRAY[id] path
  ...
UNION ALL
  SELECT
    path || id
  ...
  WHERE
    id <> ALL(T.path) AND
    array_length(T.path, 1) < 10
)

သင့်အရသာအတလက် နည်သလမ်သကို ရလေသချယ်ပါ။

source: www.habr.com

မဟတ်ချက် Add