منهنجي ڪم جي لائن جي ڪري، مون کي حالتن سان معاملو ڪرڻو پوندو جڏهن هڪ ڊولپر هڪ درخواست لکي ٿو ۽ سوچي ٿو "بنيادي سمارٽ آهي، اهو سڀ ڪجهه پاڻ کي سنڀالي سگهي ٿو!«
ڪجهه حالتن ۾ (جزوي طور تي ڊيٽابيس جي صلاحيتن جي اڻڄاڻائي کان، جزوي طور تي وقت کان اڳ جي اصلاحن کان)، اهو طريقو "فرانڪنسٽائن" جي ظاهر ٿيڻ جي ڪري ٿي.
پهرين، مان اهڙي درخواست جو هڪ مثال ڏيندس:
-- для каждой ключевой пары находим ассоциированные значения полей
WITH RECURSIVE cte_bind AS (
SELECT DISTINCT ON (key_a, key_b)
key_a a
, key_b b
, fld1 bind_fld1
, fld2 bind_fld2
FROM
tbl
)
-- находим min/max значений для каждого первого ключа
, cte_max AS (
SELECT
a
, max(bind_fld1) bind_fld1
, min(bind_fld2) bind_fld2
FROM
cte_bind
GROUP BY
a
)
-- связываем по первому ключу ключевые пары и min/max-значения
, cte_a_bind AS (
SELECT
cte_bind.a
, cte_bind.b
, cte_max.bind_fld1
, cte_max.bind_fld2
FROM
cte_bind
INNER JOIN
cte_max
ON cte_max.a = cte_bind.a
)
SELECT * FROM cte_a_bind;
هڪ درخواست جي معيار کي خاص طور تي جائزو وٺڻ لاء، اچو ته ڪجهه ترتيب واري ڊيٽا سيٽ ٺاهي:
CREATE TABLE tbl AS
SELECT
(random() * 1000)::integer key_a
, (random() * 1000)::integer key_b
, (random() * 10000)::integer fld1
, (random() * 10000)::integer fld2
FROM
generate_series(1, 10000);
CREATE INDEX ON tbl(key_a, key_b);
اهو معلوم ٿئي ٿو ته ڊيٽا پڙهڻ وقت جي چوٿين کان به گهٽ وقت ورتو پڇا ڳاڇا ڪرڻ:
ان کي ٽڪرا ٽڪرا ٽڪرا ٽڪرا ڪرڻ
اچو ته درخواست تي هڪ ويجهي نظر رکون ۽ حيران ٿي وڃو:
- WITH RECURSIVE هتي ڇو آهي جيڪڏهن هتي ريٽرسيو CTEs نه آهن؟
- ڇو گروپ منٽ/وڌ کان وڌ قدر الڳ CTE ۾ جيڪڏهن اهي پوءِ به اصل نموني سان جڙيل آهن؟
+25٪ وقت - پوئين CTE کي ورجائڻ لاءِ آخر ۾ غير مشروط 'SELECT * FROM' ڇو استعمال ڪيو وڃي؟
+14٪ وقت
ان صورت ۾، اسان ڏاڍا خوش قسمت هئاسين ته Hash Join ڪنيڪشن لاءِ چونڊيو ويو، ۽ Nested Loop نه، ڇاڪاڻ ته پوءِ اسان کي نه رڳو هڪ CTE اسڪين پاس ملي ها، پر 10K!
CTE اسڪين بابت ٿورڙوهتي اسان کي اهو ياد رکڻ گهرجي CTE اسڪين Seq Scan سان ملندڙ جلندڙ آهي - اهو آهي، ڪا به انڊيڪس نه، پر صرف هڪ مڪمل ڳولا، جنهن جي ضرورت هوندي 10K x 0.3ms = 3000MS cte_max پاران سائيڪلن لاءِ يا 1K x 1.5ms = 1500MS جڏهن cte_bind ذريعي لوپ ڪندي!
حقيقت ۾، توهان نتيجو ڇا حاصل ڪرڻ چاهيو ٿا؟ ها، عام طور تي اهو سوال آهي جيڪو 5 هين منٽ ۾ "ٽي-ڪهاڻي" سوالن جو تجزيو ڪرڻ ۾ اچي ٿو.
اسان چاهيون ٿا هر هڪ منفرد ڪنجي جوڙو لاءِ آئوٽ منٽ / وڌ ۾ وڌ گروپ کان key_a.
سو اچو ته ان لاءِ استعمال ڪريون
SELECT DISTINCT ON(key_a, key_b)
key_a a
, key_b b
, max(fld1) OVER(w) bind_fld1
, min(fld2) OVER(w) bind_fld2
FROM
tbl
WINDOW
w AS (PARTITION BY key_a);
جيئن ته ٻنهي اختيارن ۾ ڊيٽا پڙهڻ لڳ ڀڳ 4-5ms لڳن ٿا، پوء اسان جو سڄو وقت فائدو -32٪ - اهو ان جي خالص روپ ۾ آهي بيس سي پي يو تان لوڊ هٽايو ويو، جيڪڏهن اهڙي درخواست تي عمل ڪيو وڃي ته اڪثر ڪافي.
عام طور تي، توهان کي بنيادي طور تي مجبور نه ڪرڻ گهرجي ته "گول هڪ کڻو، هڪ چورس رول ڪريو."
جو ذريعو: www.habr.com