SELECT
count(*)
FROM
acc_{account_id}.urls as recordings_urls,
acc_{account_id}.recording_data as recording_data,
acc_{account_id}.sessions as sessions
WHERE
recording_data.usp_id = sessions.usp_id
AND sessions.referrer_id = recordings_urls.id
AND ( urls && array(select id from acc_{account_id}.urls where url ILIKE '%enterprise_customer.com/jobs%')::text[] )
AND r_time > to_timestamp(1542585600)
AND r_time < to_timestamp(1545177599)
AND recording_data.duration >=5
AND recording_data.num_of_pages > 0 ;
په لیست کې راتلونکی شکمن څو دی JOIN. شاید د دوی ډیر استعمال د سستیدو لامل شوی وي؟ معمولا JOINد فعالیت ستونزو لپاره خورا څرګند نوماندان دي، مګر زه باور نه لرم چې زموږ قضیه عادي وه.
analytics_db=# SELECT
count(*)
FROM
acc_{account_id}.urls as recordings_urls,
acc_{account_id}.recording_data_0 as recording_data,
acc_{account_id}.sessions_0 as sessions
WHERE
recording_data.usp_id = sessions.usp_id
AND sessions.referrer_id = recordings_urls.id
AND r_time > to_timestamp(1542585600)
AND r_time < to_timestamp(1545177599)
AND recording_data.duration >=5
AND recording_data.num_of_pages > 0 ;
count
-------
8086
(1 row)
Time: 147.851 ms
او دا هم زموږ قضیه نه وه. JOINدا خورا ګړندی ثابت شو.
د شکمنو کسانو دایره کمول
زه چمتو وم چې د هرې ممکنه فعالیت ښه والي ترلاسه کولو لپاره د پوښتنې بدلولو پیل وکړم. زما ټیم او ما دوه اصلي نظرونه رامینځته کړل:
SELECT
count(*)
FROM
acc_{account_id}.urls as recordings_urls,
acc_{account_id}.recording_data as recording_data,
acc_{account_id}.sessions as sessions
WHERE
recording_data.usp_id = sessions.usp_id
AND ( 1 = 1 )
AND sessions.referrer_id = recordings_urls.id
AND (exists(select id from acc_{account_id}.urls where url ILIKE '%enterprise_customer.com/jobs%'))
AND r_time > to_timestamp(1547585600)
AND r_time < to_timestamp(1549177599)
AND recording_data.duration >=5
AND recording_data.num_of_pages > 0 ;
count
32519
(1 row)
Time: 1636.637 ms
ښه، هو. پوښتنلیک کله چې وتړل شي EXISTS، هرڅه خورا ګړندي کوي. بله منطقي پوښتنه دا ده چې ولې غوښتنه JOIN-امي او فرعي پوښتنې پخپله په انفرادي ډول ګړندي دي ، مګر یوځای خورا ورو ورو دي؟
WITH matching_urls AS (
select id::text from acc_{account_id}.urls where url ILIKE '%enterprise_customer.com/jobs%'
)
SELECT
count(*) FROM acc_{account_id}.urls as recordings_urls,
acc_{account_id}.recording_data as recording_data,
acc_{account_id}.sessions as sessions,
matching_urls
WHERE
recording_data.usp_id = sessions.usp_id
AND ( 1 = 1 )
AND sessions.referrer_id = recordings_urls.id
AND (urls && array(SELECT id from matching_urls)::text[])
AND r_time > to_timestamp(1542585600)
AND r_time < to_timestamp(1545107599)
AND recording_data.duration >=5
AND recording_data.num_of_pages > 0;
مګر دا لاهم خورا سست و.
د مجرم موندل
په دې ټول وخت کې، زما د سترګو په وړاندې یو کوچنی شی راڅرګند شو، کوم چې ما په دوامداره توګه یو طرف پاک کړ. خو له هغه ځایه چې نور څه پاتې نه وو، ما پریکړه وکړه چې هغې ته هم وګورم. زه په اړه خبرې کوم && چلوونکی د خدای په امان EXISTS یوازې ښه فعالیت && د سست پوښتنې په ټولو نسخو کې یوازینی پاتې عام فکتور و.
کتل اسناد، موږ دا ګورو && کارول کیږي کله چې تاسو اړتیا لرئ د دوو صفونو ترمنځ عام عناصر ومومئ.
په اصلي غوښتنه کې دا دی:
AND ( urls && array(select id from acc_{account_id}.urls where url ILIKE '%enterprise_customer.com/jobs%')::text[] )
دا پدې مانا ده چې موږ په خپلو URLs کې د نمونې لټون کوو، بیا د ټولو URLs سره د ګډ پوستونو سره تقاطع ومومئ. دا یو څه ګډوډ دی ځکه چې "urls" دلته هغه جدول ته نه راجع کیږي چې ټول یو آر ایل لري، مګر په جدول کې د "urls" کالم ته اشاره کوي recording_data.
Filter: ((urls && ($0)::text[]) AND (r_time > '2018-12-17 12:17:23+00'::timestamp with time zone) AND (r_time < '2018-12-18 23:59:59+00'::timestamp with time zone) AND (duration >= '5'::double precision) AND (num_of_pages > 0))
Rows Removed by Filter: 52710
یوازې د فلټرونو څو کرښې وې &&. د دې معنی دا وه چې دا عملیات نه یوازې ګران وو، بلکې څو ځله ترسره شوي.
ما دا د حالت په جلا کولو سره ازموینه وکړه
SELECT 1
FROM
acc_{account_id}.urls as recordings_urls,
acc_{account_id}.recording_data_30 as recording_data_30,
acc_{account_id}.sessions_30 as sessions_30
WHERE
urls && array(select id from acc_{account_id}.urls where url ILIKE '%enterprise_customer.com/jobs%')::text[]
دا پوښتنه ورو وه. ځکه چې د JOIN-s ګړندي دي او فرعي پوښتنې ګړندي دي ، یوازینی شی پاتې و && چلوونکی
دا یوازې یو مهم عملیات دی. موږ تل اړتیا لرو چې د یو نمونې لټون کولو لپاره د URLs بشپړ لاندې جدول وپلټئ، او موږ تل د تقاطع موندلو ته اړتیا لرو. موږ نشو کولی په مستقیم ډول د URL ریکارډونو پلټنه وکړو، ځکه چې دا یوازې IDs ته اشاره کوي urls.
SELECT urls.url
FROM
acc_{account_id}.urls as urls,
(SELECT unnest(recording_data.urls) AS id) AS unrolled_urls
WHERE
urls.id = unrolled_urls.id AND
urls.url ILIKE '%jobs%'
د هغې پرځای JOIN نحو ما یوازې یوه فرعي پوښتنه کارولې او پراخه کړې recording_data.urls د دې لپاره چې تاسو کولی شئ په مستقیم ډول شرایط پلي کړئ WHERE.
دلته ترټولو مهمه خبره دا ده && د دې لپاره کارول کیږي چې وګوري ایا ورکړل شوې ننوتنې یو ورته URL لري. که تاسو لږ څه وخورئ، تاسو لیدلی شئ چې دا عملیات د صفونو عناصرو (یا د میز قطارونو) له لارې حرکت کوي او کله چې یو شرط (میچ) پوره شي ودریږي. ایا تاسو ته هیڅ شی نه یادوي؟ هو، EXISTS.
SELECT
count(*)
FROM
acc_{account_id}.urls as recordings_urls,
acc_{account_id}.recording_data as recording_data,
acc_{account_id}.sessions as sessions
WHERE
recording_data.usp_id = sessions.usp_id
AND ( 1 = 1 )
AND sessions.referrer_id = recordings_urls.id
AND r_time > to_timestamp(1542585600)
AND r_time < to_timestamp(1545177599)
AND recording_data.duration >=5
AND recording_data.num_of_pages > 0
AND EXISTS(
SELECT urls.url
FROM
acc_{account_id}.urls as urls,
(SELECT unnest(urls) AS rec_url_id FROM acc_{account_id}.recording_data)
AS unrolled_urls
WHERE
urls.id = unrolled_urls.rec_url_id AND
urls.url ILIKE '%enterprise_customer.com/jobs%'
);
او وروستی لیډ وخت Time: 1898.717 ms د لمانځلو وخت؟!؟
ډیر تیز نه! لومړی تاسو اړتیا لرئ د سموالي معاینه وکړئ. زه ډیر شکمن وم EXISTS اصلاح کول لکه څنګه چې دا د مخکې پای ته رسولو لپاره منطق بدلوي. موږ اړتیا لرو ډاډ ترلاسه کړو چې موږ په غوښتنې کې غیر څرګند غلطی نه دی اضافه کړی.