PostgreSQL Antipatterns- "တစ်ခုပဲကျန်တော့တယ်!"

SQL တွင် သင်သည် သင်အောင်မြင်လိုသော "အရာကို" နှင့် "မည်ကဲ့သို့" လုပ်ဆောင်ရမည်ကို ဖော်ပြခြင်းမပြုဘဲ ဖော်ပြသည်။ ထို့ကြောင့်၊ “ကြားသည်အတိုင်း ရေးထားပုံ” ပုံစံဖြင့် SQL queries ကို တီထွင်ခြင်း၏ ပြဿနာသည် ၎င်း၏နေရာတွင် ဂုဏ်ယူစရာဖြစ်သည်။ SQL ရှိ အခြေအနေများကို တွက်ချက်ခြင်း၏ အင်္ဂါရပ်များ.

ယနေ့တွင်၊ အလွန်ရိုးရှင်းသော ဥပမာများကို အသုံးပြု၍ ဤအရာသည် အသုံးပြုမှု၏ ဆက်စပ်မှုကို ဖြစ်ပေါ်စေနိုင်သည်ကို ကြည့်ကြပါစို့ GROUP/DISTINCT и LIMIT သူတို့နှင့်အတူ။

အခု တောင်းဆိုချက်ထဲမှာ ရေးထားတယ်ဆိုရင်၊ “အရင်ဆုံး ဒီဆိုင်းဘုတ်တွေကို ချိတ်ပြီး ထပ်နေတဲ့ အားလုံးကို လွှင့်ပစ်ပါ။ တစ်ခုပဲကျန်တော့တယ်။ သော့တစ်ခုစီအတွက် မိတ္တူ" - ချိတ်ဆက်မှု လုံးဝမလိုအပ်သော်လည်း ၎င်းသည် မည်သို့အလုပ်လုပ်မည်ကို အတိအကျဖော်ပြသည်။

တစ်ခါတစ်ရံတွင် သင်သည် ကံကောင်းပြီး ၎င်းသည် "အလုပ်လုပ်သည်"၊ တစ်ခါတစ်ရံတွင် ၎င်းသည် စွမ်းဆောင်ရည်အပေါ် မနှစ်မြို့ဖွယ်အကျိုးသက်ရောက်မှုများရှိပြီး တစ်ခါတစ်ရံတွင် ဆော့ဖ်ဝဲရေးသားသူ၏အမြင်မှ လုံးဝမထင်မှတ်ထားသော အကျိုးသက်ရောက်မှုများကို ပေးပါသည်။

PostgreSQL Antipatterns- "တစ်ခုပဲကျန်တော့တယ်!"
သိပ်ကြီးကျယ်ခမ်းနားတာတော့မဟုတ်ပေမယ့်...

"ချစ်စရာကောင်းသောစုံတွဲ"- JOIN + DISTINCT

SELECT DISTINCT
  X.*
FROM
  X
JOIN
  Y
    ON Y.fk = X.pk
WHERE
  Y.bool_condition;

သူတို့ဘာလိုချင်တယ်ဆိုတာ ရှင်းပါတယ်။ ပြည့်စုံသောအခြေအနေနှင့် သက်ဆိုင်သည့် Y တွင် မှတ်တမ်းများပါရှိသည့် မှတ်တမ်း X ကို ရွေးပါ။. ကတဆင့် တောင်းဆိုရေးသားခဲ့ပါတယ်။ JOIN — အချို့သော pk တန်ဖိုးများကို အကြိမ်ပေါင်းများစွာ ရရှိခဲ့သည် (Y တွင် သင့်လျော်သော ထည့်သွင်းမှုများမည်မျှရှိသည်)။ ဘယ်လိုဖယ်ရှားရမလဲ။ သေချာတယ်။ DISTINCT!

X-record တစ်ခုစီအတွက် ဆက်စပ် Y-records ရာပေါင်းများစွာရှိပြီး၊ ထို့နောက် ထပ်တူများကို သူရဲကောင်းဆန်ဆန် ဖယ်ရှားသည့်အခါ အထူးသဖြင့် "ကျေနပ်စရာ" ဖြစ်ပါသည်...

PostgreSQL Antipatterns- "တစ်ခုပဲကျန်တော့တယ်!"

ဘယ်လိုပြင်ရမလဲ။ စတင်ရန်၊ ပြဿနာကို ပြုပြင်နိုင်သည်ကို သဘောပေါက်ပါ။ "Y တွင် ပြည့်စုံသောအခြေအနေနှင့် ဆက်စပ်နေသော အနည်းဆုံးတစ်ခုရှိမည့် မှတ်တမ်း X ကို ရွေးပါ" - နောက်ဆုံးအနေနဲ့၊ Y-record ကိုယ်တိုင်က ဘာမှမလိုအပ်ပါဘူး။

တည်ရှိနေပါသည်။

SELECT
  *
FROM
  X
WHERE
  EXISTS(
    SELECT
      NULL
    FROM
      Y
    WHERE
      fk = X.pk AND
      bool_condition
    LIMIT 1
  );

PostgreSQL ၏အချို့သောဗားရှင်းများသည် EXISTS တွင်တက်လာသောပထမဆုံး entry ကိုရှာရန်လုံလောက်သည်၊ အဟောင်းများသည်မရှာပါ။ ထို့ကြောင့် ကျွန်တော် အမြဲတမ်း ထောက်ပြလိုပါသည်။ LIMIT 1 အတွင်း EXISTS.

တစ်ဖက်မှပူးပေါင်းပါ။

SELECT
  X.*
FROM
  X
, LATERAL (
    SELECT
      Y.*
    FROM
      Y
    WHERE
      fk = X.pk AND
      bool_condition
    LIMIT 1
  ) Y
WHERE
  Y IS DISTINCT FROM NULL;

တူညီသောရွေးချယ်မှုသည် လိုအပ်ပါက၊ ဆက်စပ် Y-မှတ်တမ်းမှ ဒေတာအချို့ကို ချက်ချင်းပြန်ပို့ရန် ခွင့်ပြုသည်။ အလားတူရွေးချယ်မှုကို ဆောင်းပါးတွင် ဆွေးနွေးထားသည်။ "PostgreSQL Antipatterns- ရှားပါးသောမှတ်တမ်းသည် JOIN ၏အလယ်သို့ရောက်ရှိလိမ့်မည်".

“ဘာကြောင့် ပိုပေးရသလဲ”- ကွဲပြား [ဖွင့်] + ကန့်သတ်ချက် ၁

ထိုသို့သောမေးခွန်းအသွင်ပြောင်းခြင်း၏နောက်ထပ်အကျိုးကျေးဇူးတစ်ခုမှာ အောက်ပါကိစ္စများတွင်ကဲ့သို့ ၎င်းတို့အနက်မှတစ်ခု သို့မဟုတ် အနည်းငယ်သာလိုအပ်ပါက မှတ်တမ်းများရှာဖွေမှုကို အလွယ်တကူကန့်သတ်နိုင်သည်-

SELECT DISTINCT ON(X.pk)
  *
FROM
  X
JOIN
  Y
    ON Y.fk = X.pk
LIMIT 1;

ယခုကျွန်ုပ်တို့တောင်းဆိုချက်ကိုဖတ်ပြီး DBMS မှလုပ်ဆောင်ရန်အဆိုပြုထားသည်ကိုနားလည်ရန်ကြိုးစားပါ-

  • ဆိုင်းဘုတ်များချိတ်ဆက်ခြင်း။
  • X.pk မှထူးခြားသည်။
  • ကျန်ရှိသော entry များမှ တစ်ခုကို ရွေးပါ။

ဒါဆို မင်းဘာရခဲ့လဲ။ "အဝင်​တစ်​ခုပဲ" တမူထူးခြားသူများထံမှ - ဤထူးခြားသည့်အရာများကို ကျွန်ုပ်တို့ယူပါက ရလဒ်သည် တစ်နည်းတစ်ဖုံ ပြောင်းလဲသွားပါမည်လား?...

SELECT
  *
FROM
  (
    SELECT
      *
    FROM
      X
    -- сюда можно подсунуть подходящих условий
    LIMIT 1 -- +1 Limit
  ) X
JOIN
  Y
    ON Y.fk = X.pk
LIMIT 1;

ခေါင်းစဉ်နဲ့ အတိအကျ အတူတူပါပဲ။ GROUP BY + LIMIT 1.

"ငါမေးစရာရှိတယ်"- သွယ်ဝိုက်သောအုပ်စု + ကန့်သတ်ချက်

တူညီသောအရာများ ကွဲပြားစွာ ဖြစ်ပေါ်တတ်သည်။ အချည်းနှီးမဟုတ်သောစစ်ဆေးမှုများ တောင်းဆိုမှု တိုးတက်လာသည်နှင့်အမျှ ဆိုင်းဘုတ်များ သို့မဟုတ် CTE များ

...
CASE
  WHEN (
    SELECT
      count(*)
    FROM
      X
    LIMIT 1
  ) = 0 THEN ...

စုစည်းလုပ်ဆောင်ချက်များ (count/min/max/sum/...) တိကျပြတ်သားသော ညွှန်ကြားချက်များမပါဘဲ အစုတစ်ခုလုံးတွင် အောင်မြင်စွာ လုပ်ဆောင်နေပါသည်။ GROUP BY. နှင့်သာ LIMIT သူတို့က သိပ်ဖော်ရွေတာ မဟုတ်ဘူး။

developer က စဉ်းစားလို့ရတယ်။ "အဲဒီမှာ မှတ်တမ်းတွေရှိရင် ကန့်သတ်ချက်ထက် ပိုမလိုဘူး". ဒါပေမယ့် မလုပ်ပါနဲ့! အခြေအမြစ်ရှိသောကြောင့်၊

  • သူတို့လိုချင်တာကို ရေတွက်ပါ။ မှတ်တမ်းအားလုံးအရ
  • သူတို့တောင်းသလောက် စာကြောင်းများများပေးပါ။

ပစ်မှတ်အခြေအနေများပေါ် မူတည်၍ အောက်ပါ အစားထိုးမှုများထဲမှ တစ်ခုကို ပြုလုပ်ရန် သင့်လျော်သည်-

  • (count + LIMIT 1) = 0 အပေါ် NOT EXISTS(LIMIT 1)
  • (count + LIMIT 1) > 0 အပေါ် EXISTS(LIMIT 1)
  • count >= N အပေါ် (SELECT count(*) FROM (... LIMIT N))

“ဂရမ်တွင် ဆွဲထားရန် မည်မျှရှိသည်”- ကွဲပြားချက် + ကန့်သတ်ချက်

SELECT DISTINCT
  pk
FROM
  X
LIMIT $1

နုံအသော ဆော့ဖ်ဝဲရေးသားသူသည် တောင်းဆိုချက်အား လုပ်ဆောင်နေခြင်းကို ရပ်သွားလိမ့်မည်ဟု စိတ်ရင်းမှန်ဖြင့် ယုံကြည်နိုင်ပါသည်။ ပထမဆုံး မတူညီတဲ့ တန်ဖိုးတွေရဲ့ $1 ကို တွေ့တာနဲ့ တွေ့တယ်။.

နောင်တစ်ချိန်ချိန်တွင် ၎င်းသည် node အသစ်တစ်ခုကြောင့် အလုပ်လုပ်နိုင်မည်ဖြစ်သည်။ အညွှန်း Skip Scanလက်ရှိ အကောင်အထည်ဖော် ဆောင်ရွက်နေသော်လည်း အကောင်အထည်ဖော်မှု မရှိသေးကြောင်း သိရသည်။

လောလောဆယ်တော့ ပထမ မှတ်တမ်းအားလုံးကို ပြန်လည်ရယူပါမည်။၊ သည် ထူးခြားပြီး ၎င်းတို့ထံမှသာ တောင်းဆိုထားသော ပမာဏကို ပြန်ပေးမည်ဖြစ်သည်။ တစ်ခုခုကို လိုချင်ရင် အထူးသဖြင့် စိတ်မကောင်းဘူး။ $ 1 = 4ပြီးတော့ ဇယားထဲမှာ မှတ်တမ်းပေါင်း ရာနဲ့ချီ ရှိတယ်။

အချည်းနှီး ဝမ်းနည်းခြင်း မဖြစ်စေရန်၊ ထပ်တလဲလဲ မေးမြန်းချက်ကို သုံးကြည့်ရအောင် PostgreSQL Wiki မှ "DISTINCT is for the poor":

PostgreSQL Antipatterns- "တစ်ခုပဲကျန်တော့တယ်!"

source: www.habr.com

မှတ်ချက် Add