PostgreSQL Antipatterns: "هڪ ئي هجڻ گهرجي!"

SQL ۾، توھان بيان ڪريو ٿا "ڇا" توھان حاصل ڪرڻ چاھيو ٿا، نه ته "ڪيئن" ان تي عمل ڪيو وڃي. تنهن ڪري، SQL سوالن جي انداز ۾ ترقي ڪرڻ جو مسئلو "جيئن اهو ٻڌو ويو آهي ته اهو ڪيئن لکيو ويو آهي" پنهنجي عزت جي جاء وٺندو آهي. SQL ۾ حالتن جي حساب سان خاصيتون.

اڄ، انتهائي سادي مثالن کي استعمال ڪندي، اچو ته ڏسو ته هي استعمال جي حوالي سان ڇا ٿي سگهي ٿو GROUP/DISTINCT и LIMIT انهن سان.

هاڻي، جيڪڏهن توهان درخواست ۾ لکيو "پهرين انهن نشانين کي ڳنڍيو، ۽ پوء سڀني نقلن کي ڪڍي ڇڏيو، اتي صرف هڪ رهڻ گهرجي هر چاٻي لاء ڪاپي " - اهو بلڪل آهي ته اهو ڪيئن ڪم ڪندو، جيتوڻيڪ ڪنيڪشن جي ضرورت نه هئي.

۽ ڪڏهن ڪڏهن توهان خوش قسمت آهيو ۽ اهو "صرف ڪم ڪري ٿو"، ڪڏهن ڪڏهن اهو ڪارڪردگي تي ناپسنديده اثر آهي، ۽ ڪڏهن ڪڏهن اهو اثر ڏئي ٿو جيڪو ڊولپر جي نقطي نظر کان مڪمل طور تي غير متوقع آهي.

PostgreSQL Antipatterns: "هڪ ئي هجڻ گهرجي!"
خير، شايد ايترو شاندار نه، پر ...

”مٺي جوڙو“: شامل ٿيو + ڌار

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

اهو واضح ٿي ويندو ته اهي ڇا چاهيندا آهن رڪارڊز X چونڊيو جنهن لاءِ Y ۾ رڪارڊ موجود آهن جيڪي پوري ٿيڻ واري حالت سان لاڳاپيل آهن. جي ذريعي درخواست لکي JOIN - ڪي پي ڪي قدر ڪيترائي ڀيرا مليا (حقيقي طور تي Y ۾ ڪيتريون مناسب داخلون ظاهر ٿيون). ڪيئن هٽائڻ لاء؟ يقينن DISTINCT!

اهو خاص طور تي ”خوشگوار“ آهي جڏهن هر ايڪس رڪارڊ لاءِ ڪيترائي سو لاڳاپيل Y-ريڪارڊ هوندا آهن، ۽ پوءِ نقلن کي بهادريءَ سان هٽايو ويندو آهي...

PostgreSQL Antipatterns: "هڪ ئي هجڻ گهرجي!"

ڪيئن ٺيڪ ڪرڻ لاء؟ شروع ڪرڻ سان، سمجھو ته مسئلو کي تبديل ڪري سگھجي ٿو "ريڪارڊ چونڊيو X جنهن لاءِ Y ۾ گهٽ ۾ گهٽ هڪ آهي جيڪو پورو ٿيل شرط سان لاڳاپيل آهي" - سڀ کان پوء، اسان کي Y-ريڪارڊ مان ڪنهن به شيء جي ضرورت ناهي.

Nested EXISTS

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

PostgreSQL جا ڪجهه ورجن سمجهن ٿا ته EXISTS ۾ اهو ڪافي آهي ته پهرين داخل ٿيڻ کي ڳولڻ لاءِ، پراڻن وارا نه. تنهن ڪري مان هميشه اشارو ڪرڻ چاهيان ٿو 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-record مان ڪجهه ڊيٽا واپس ڪرڻ لاء. ساڳئي اختيار جي مضمون ۾ بحث ڪيو ويندو "PostgreSQL Antipatterns: هڪ نادر رڪارڊ شامل ٿيڻ جي وچ ۾ پهچي ويندو".

”وڌيڪ ڇو ڏيو“: DISTINCT [ON] + LIMIT 1

اهڙن سوالن جي تبديلين جو هڪ اضافي فائدو اهو آهي ته رڪارڊ جي ڳولا کي آساني سان محدود ڪرڻ جي صلاحيت آهي جيڪڏهن انهن مان صرف هڪ يا ڪجهه گهربل هجي، جيئن هيٺين صورت ۾:

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

ھاڻي اسان درخواست پڙھون ٿا ۽ سمجھڻ جي ڪوشش ڪريون ٿا ته DBMS ڇا ڪرڻ جي تجويز آھي:

  • نشانين کي ڳنڍڻ
  • منفرد طرفان X.pk
  • باقي داخلائن مان، ھڪڙو چونڊيو

پوءِ توکي ڇا مليو؟ "صرف هڪ داخلا" منفرد کان - ۽ جيڪڏهن اسان هن کي غير منفرد مان هڪ کڻون ٿا، نتيجو ڪنهن به طرح تبديل ٿيندو؟.. "۽ جيڪڏهن ڪو فرق ناهي، ڇو وڌيڪ ادا ڪيو؟"

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

۽ بلڪل ساڳئي موضوع سان GROUP BY + LIMIT 1.

"مون کي صرف پڇڻو آهي": ضمني گروپ + LIMIT

ساڳيون شيون مختلف وقتن تي ٿينديون آهن غير خالي جي چڪاس نشانيون يا CTEs جيئن درخواست جاري آهي:

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

مجموعي افعال (count/min/max/sum/...) پوري سيٽ تي ڪاميابيءَ سان عمل ڪيو ويو آهي، جيتوڻيڪ واضح هدايتن کان سواءِ GROUP BY. صرف سان LIMIT اهي ڏاڍا دوست نه آهن.

ڊولپر سوچي سگهي ٿو "جيڪڏهن اتي رڪارڊ موجود آهن، پوء مون کي LIMIT کان وڌيڪ نه گهرجي". پر ائين نه ڪر! ڇاڪاڻ ته بنيادي طور تي اهو آهي:

  • ڳڻيو جيڪي اهي چاهين ٿا سڀني رڪارڊ جي مطابق
  • جيتريون لائينون اھي پڇن ٿيون

ھدف جي حالتن تي مدار رکندي، اھو مناسب آھي ھيٺ ڏنل متبادل مان ھڪڙو ٺاھيو:

  • (count + LIMIT 1) = 0 تي NOT EXISTS(LIMIT 1)
  • (count + LIMIT 1) > 0 تي EXISTS(LIMIT 1)
  • count >= N تي (SELECT count(*) FROM (... LIMIT N))

”گرام ۾ ڪيترو رکڻو آهي“: DISTINCT + LIMIT

SELECT DISTINCT
  pk
FROM
  X
LIMIT $1

هڪ بيوقوف ڊولپر شايد خلوص سان يقين رکون ٿا ته درخواست تي عمل ٿيڻ بند ٿي ويندو. جيئن ئي اسان پهرين مختلف قدرن مان $1 ڳوليندا آهيون جيڪي سامهون اچن ٿا.

ڪجهه وقت مستقبل ۾ اهو ٿي سگهي ٿو ۽ ڪم ڪندو هڪ نئين نوڊ جي مهرباني Index Skip Scanجنهن تي هن وقت ڪم ٿي رهيو آهي، پر اڃا تائين نه ٿيو آهي.

في الحال پهريون سڀ رڪارڊ حاصل ڪيا ويندا، منفرد آهن، ۽ صرف انهن مان گهربل رقم واپس ڪئي ويندي. اهو خاص طور تي اداس آهي جيڪڏهن اسان ڪجهه چاهيون ٿا $ 1 = 4، ۽ ٽيبل ۾ سوين هزارين رڪارڊ موجود آهن ...

بيڪار ۾ غمگين نه ٿيڻ لاء، اچو ته استعمال ڪريون هڪ بار بار سوال PostgreSQL Wiki مان "DISTINCT غريبن لاءِ آهي".:

PostgreSQL Antipatterns: "هڪ ئي هجڻ گهرجي!"

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

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