Ин сайт як тонна трафик дошт ва мо танҳо барои он беш аз як миллион URL-и беназирро нигоҳ медоштем. Ва онҳо мехостанд як қолаби оддии URL-ро пайдо кунанд, ки ба модели тиҷоратии онҳо алоқаманд аст.
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 ;
Ва инҳо вақтҳо ҳастанд:
Вақти ба нақша гирифташуда: 1.480 ms Вақти иҷро: 1431924.650 ms
Дархост 150 ҳазор сатрро аз назар гузаронд. Банақшагирандаи пурсиш якчанд тафсилоти ҷолибро нишон дод, аммо монеаҳои возеҳ набуд.
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
EXISTS-ро барои URL зерпурсиш истифода баред: Мо мехостем бори дигар тафтиш кунем, ки оё дар зерпурсиш барои URL ягон мушкилот вуҷуд дорад. Яке аз роҳҳои ноил шудан ба ин истифодаи оддӣ аст EXISTS. 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 (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
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[] )
Ин маънои онро дорад, ки мо дар URL-ҳои худ намунаи ҷустуҷӯ мекунем ва пас чорроҳаро бо ҳама URL-ҳо бо паёмҳои умумӣ пайдо мекунем. Ин каме печида аст, зеро "urls" дар ин ҷо на ба ҷадвали дорои ҳама URL-ҳо, балки ба сутуни "urls" дар ҷадвал ишора мекунад. recording_data.
Бо шубҳаҳои афзоянда дар бораи &&, Ман кӯшиш кардам, ки тасдиқи онҳоро дар нақшаи дархости тавлидшуда пайдо кунам EXPLAIN ANALYZE (Ман аллакай нақшаи захира доштам, аммо ман одатан дар SQL озмоиш кардан бароҳаттар аз кӯшиши фаҳмидани шаффофияти банақшагирандагони дархостҳо ҳастам).
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[]
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%'
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%'
);
Мо аз вақти пурсиш аз ~ 24 дақиқа то 2 сония гузаштем - хеле афзоиши назарраси иҷроиш! Гарчанде ки ин мақола калон баромад, ҳама таҷрибаҳое, ки мо анҷом додем, дар як рӯз сурат гирифтанд ва ҳисоб карда шуд, ки онҳо барои оптимизатсия ва санҷиш аз 1,5 то 2 соат вақт сарф карданд.
SQL забони олиҷаноб аст, агар шумо аз он натарсед, аммо кӯшиш кунед, ки онро омӯзед ва истифода баред. Бо фаҳмиши хуб дар бораи чӣ гуна иҷро кардани дархостҳои SQL, чӣ гуна пойгоҳи додаҳо нақшаҳои дархостро тавлид мекунад, чӣ гуна кор кардани индексҳо ва танҳо андозаи маълумоте, ки шумо бо он сарукор доред, шумо метавонед дар оптимизатсияи дархостҳо муваффақ бошед. Бо вуҷуди ин, идома додани кӯшиши равишҳои гуногун ва оҳиста-оҳиста бартараф кардани мушкилот, пайдо кардани монеаҳо муҳим аст.
Қисмати беҳтарини ба даст овардани чунин натиҷаҳо ин беҳбуди назаррас ва намоёни суръат аст - дар он гузорише, ки қаблан ҳатто бор намешуд, ҳоло қариб фавран бор мешавад.
Ташаккури махсус ба рафикони ман бо фармони Адитя Мишра, Адитя Гауру и Варун Малхотра барои хучуми майна ва Динкар Пандир барои дарёфти хатои муҳим дар дархости ниҳоии мо пеш аз он ки дар ниҳоят бо он хайрухуш кунем!