ማቋቋሚያዎችን ከሚያመጡ ስራዎች ይጠንቀቁ...
ትንሽ መጠይቅን እንደ ምሳሌ በመጠቀም፣ በPostgreSQL ውስጥ መጠይቆችን ለማመቻቸት አንዳንድ ሁለንተናዊ አቀራረቦችን እንመልከት። እነሱን መጠቀም ወይም አለመጠቀም የእርስዎ ነው, ነገር ግን ስለእነሱ ማወቅ ጠቃሚ ነው.
በአንዳንድ ተከታይ የፒጂ ስሪቶች መርሐግብር አውጪው ይበልጥ ብልጥ በሚሆንበት ጊዜ ሁኔታው ሊለወጥ ይችላል, ነገር ግን ለ 9.4/9.6 እዚህ ምሳሌዎች ውስጥ እንደሚታየው በግምት ተመሳሳይ ይመስላል.
በጣም እውነተኛ ጥያቄ እንውሰድ፡-
SELECT
TRUE
FROM
"Документ" d
INNER JOIN
"ДокументРасширение" doc_ex
USING("@Документ")
INNER JOIN
"ТипДокумента" t_doc ON
t_doc."@ТипДокумента" = d."ТипДокумента"
WHERE
(d."Лицо3" = 19091 or d."Сотрудник" = 19091) AND
d."$Черновик" IS NULL AND
d."Удален" IS NOT TRUE AND
doc_ex."Состояние"[1] IS TRUE AND
t_doc."ТипДокумента" = 'ПланРабот'
LIMIT 1;
ስለ ጠረጴዛ እና የመስክ ስሞችየሜዳዎች እና የጠረጴዛዎች "የሩሲያ" ስሞች በተለየ መንገድ ሊታከሙ ይችላሉ, ግን ይህ የጣዕም ጉዳይ ነው. ምክንያቱም
የተገኘውን እቅድ እንመልከት፡-
144ms እና ወደ 53ሺህ የሚጠጉ ማቋቋሚያዎች - ማለትም ከ 400MB በላይ ውሂብ! እና በጥያቄያችን ጊዜ ሁሉም በካሼው ውስጥ ካሉ እድለኞች እንሆናለን, አለበለዚያ ከዲስክ ሲነበብ ብዙ ጊዜ ይወስዳል.
አልጎሪዝም በጣም አስፈላጊ ነው!
ማንኛውንም ጥያቄ እንደምንም ለማመቻቸት መጀመሪያ ምን ማድረግ እንዳለበት መረዳት አለቦት።
የዳታቤዝ አወቃቀሩን እድገት ከዚ ጽሑፍ ወሰን ውጭ ለጊዜው እንተወውና በአንፃራዊነት “በርካሽ” እንደምንችል እንስማማለን። ጥያቄውን እንደገና ይፃፉ እና/ወይም የምንፈልጋቸውን አንዳንድ ነገሮች በመሠረቱ ላይ ያንከባለሉ ማውጫዎች.
ስለዚህ ጥያቄው:
- ቢያንስ የተወሰነ ሰነድ መኖሩን ያረጋግጣል
- በምንፈልገው ሁኔታ እና በተወሰነ ዓይነት
- ደራሲው ወይም ፈፃሚው የምንፈልገው ሰራተኛ ከሆነ
ይቀላቀሉ + LIMIT 1
ብዙ ሠንጠረዦች መጀመሪያ የተቀላቀሉበት ጥያቄ ለመጻፍ ብዙ ጊዜ ለገንቢ ይቀላል፣ እና ከዚያ ከዚህ ስብስብ አንድ መዝገብ ብቻ ይቀራል። ግን ለገንቢው ቀላል ማለት ለዳታቤዝ የበለጠ ቀልጣፋ ማለት አይደለም።
በእኛ ሁኔታ 3 ጠረጴዛዎች ብቻ ነበሩ - ውጤቱስ ምንድ ነው?
በመጀመሪያ ከ "የሰነድ አይነት" ሰንጠረዥ ጋር ያለውን ግንኙነት እናስወግድ, እና በተመሳሳይ ጊዜ የውሂብ ጎታውን ይንገሩ የኛ አይነት መዝገብ ልዩ ነው። (ይህን እናውቃለን፣ ግን የጊዜ ሰሌዳ አስማሚው እስካሁን ምንም ሀሳብ የለውም)
WITH T AS (
SELECT
"@ТипДокумента"
FROM
"ТипДокумента"
WHERE
"ТипДокумента" = 'ПланРабот'
LIMIT 1
)
...
WHERE
d."ТипДокумента" = (TABLE T)
...
አዎ፣ ሠንጠረዡ/CTE የአንድ ሪከርድ አንድ ነጠላ መስክ ካካተተ፣በፒጂ ውስጥ ከመፃፍ ይልቅ እንደዚህ መፃፍ ይችላሉ።
d."ТипДокумента" = (SELECT "@ТипДокумента" FROM T LIMIT 1)
በPostgreSQL መጠይቆች ውስጥ ሰነፍ ግምገማ
BitmapOr vs UNION
በአንዳንድ ሁኔታዎች ቢትማፕ ሂፕ ስካን ብዙ ያስከፍለናል - ለምሳሌ በእኛ ሁኔታ ብዙ መዝገቦች የሚፈለገውን ሁኔታ ሲያሟሉ። ያገኘነው ምክንያቱም ወይም ሁኔታ ወደ BitmapOr ተለወጠ- በእቅድ ውስጥ ክወና.
ወደ መጀመሪያው ችግር እንመለስ - ተዛማጅ መዝገብ ማግኘት አለብን ማንኛውም ከሁኔታዎች - ማለትም በሁለቱም ሁኔታዎች ሁሉንም 59K መዛግብት መፈለግ አያስፈልግም. አንድ ሁኔታን ለመሥራት አንድ መንገድ አለ, እና በመጀመሪያው ላይ ምንም ነገር ካልተገኘ ብቻ ወደ ሁለተኛው ይሂዱ. የሚከተለው ንድፍ ይረዳናል:
(
SELECT
...
LIMIT 1
)
UNION ALL
(
SELECT
...
LIMIT 1
)
LIMIT 1
"ውጫዊ" LIMIT 1 ፍለጋው የሚያበቃው የመጀመሪያው መዝገብ ሲገኝ መሆኑን ያረጋግጣል። እና በመጀመሪያው እገዳ ውስጥ ቀድሞውኑ ከተገኘ, ሁለተኛው እገዳ አይተገበርም (ፈጽሞ አልተገደለም በተመለከተ)።
"በ CASE ስር አስቸጋሪ ሁኔታዎችን መደበቅ"
በመጀመሪያው መጠይቅ ውስጥ በጣም የማይመች ጊዜ አለ - ሁኔታውን ከተዛማጅ ሠንጠረዥ "ሰነድ ኤክስቴንሽን" ጋር መፈተሽ። በገለፃው ውስጥ ያሉ ሌሎች ሁኔታዎች እውነት ምንም ቢሆኑም (ለምሳሌ ፣ መ.“ተሰርዟል” እውነት አይደለም።), ይህ ግንኙነት ሁል ጊዜ ይከናወናል እና "ሀብቶችን ያስከፍላል". ከእነሱ ብዙ ወይም ያነሰ ወጪ ይደረጋል - በዚህ ሰንጠረዥ መጠን ይወሰናል.
ግን ተዛማጅነት ያለው መዝገብ መፈለግ በጣም አስፈላጊ በሚሆንበት ጊዜ ብቻ እንዲከሰት መጠይቁን ማስተካከል ይችላሉ፡
SELECT
...
FROM
"Документ" d
WHERE
... /*index cond*/ AND
CASE
WHEN "$Черновик" IS NULL AND "Удален" IS NOT TRUE THEN (
SELECT
"Состояние"[1] IS TRUE
FROM
"ДокументРасширение"
WHERE
"@Документ" = d."@Документ"
)
END
አንዴ ከተገናኘው ጠረጴዛ ወደ እኛ ለውጤቱ የትኛውም መስክ አያስፈልግም, ከዚያ JOINን በንዑስ መጠይቅ ላይ ወደ ሁኔታ የመቀየር እድል አለን።
በመረጃ ጠቋሚ የተቀመጡትን መስኮች “ከ CASE ቅንፎች ውጭ” እንተዋቸው ፣ ቀላል ሁኔታዎችን ከመዝገቡ ወደ WHEN ብሎክ እንጨምር - እና አሁን “ከባድ” መጠይቁ የሚከናወነው ወደ THEN ሲያልፍ ብቻ ነው።
የመጨረሻ ስሜ "ጠቅላላ" ነው
ውጤቱን ከላይ ከተገለጹት ሁሉም መካኒኮች ጋር እንሰበስባለን-
WITH T AS (
SELECT
"@ТипДокумента"
FROM
"ТипДокумента"
WHERE
"ТипДокумента" = 'ПланРабот'
)
(
SELECT
TRUE
FROM
"Документ" d
WHERE
("Лицо3", "ТипДокумента") = (19091, (TABLE T)) AND
CASE
WHEN "$Черновик" IS NULL AND "Удален" IS NOT TRUE THEN (
SELECT
"Состояние"[1] IS TRUE
FROM
"ДокументРасширение"
WHERE
"@Документ" = d."@Документ"
)
END
LIMIT 1
)
UNION ALL
(
SELECT
TRUE
FROM
"Документ" d
WHERE
("ТипДокумента", "Сотрудник") = ((TABLE T), 19091) AND
CASE
WHEN "$Черновик" IS NULL AND "Удален" IS NOT TRUE THEN (
SELECT
"Состояние"[1] IS TRUE
FROM
"ДокументРасширение"
WHERE
"@Документ" = d."@Документ"
)
END
LIMIT 1
)
LIMIT 1;
[ወደ] ኢንዴክሶች በማስተካከል ላይ
የሰለጠነ ዓይን በ UNION ንዑስ ብሎኮች ውስጥ ያሉት ጠቋሚ ሁኔታዎች ትንሽ ለየት ያሉ መሆናቸውን አስተውሏል - ይህ የሆነበት ምክንያት በጠረጴዛው ላይ ተስማሚ ኢንዴክሶች ስላሉን ነው። እና እነሱ ከሌሉ ፣ መፍጠር ጠቃሚ ይሆናል- ሰነድ (ሰው 3፣ ሰነድ ዓይነት) и ሰነድ (የሰነድ ዓይነት፣ ተቀጣሪ).
በ ROW ሁኔታዎች ውስጥ ስለ መስኮች ቅደም ተከተልከእቅድ አውጪው እይታ, በእርግጥ, መጻፍ ይችላሉ (A፣ B) = (constA፣ constB)ና (B፣ A) = (constB፣ constA). ነገር ግን በሚቀዳበት ጊዜ በመረጃ ጠቋሚው ውስጥ ባሉት መስኮች ቅደም ተከተል, እንዲህ ዓይነቱ ጥያቄ በኋላ ላይ ለማረም በቀላሉ የበለጠ አመቺ ነው.
በእቅዱ ውስጥ ምን አለ?
እንደ አለመታደል ሆኖ እኛ እድለኞች አልነበርንም እና በመጀመሪያው UNION ብሎክ ውስጥ ምንም ነገር አልተገኘም, ስለዚህ ሁለተኛው አሁንም ተገድሏል. ግን እንደዚያም - ብቻ 0.037ms እና 11 ቋቶች!
ጥያቄውን አፋጥነናል እና በሜሞሪ ውስጥ ያለውን የመረጃ ፍሰት ቀንሷል ብዙ ሺህ ጊዜ, በአግባቡ ቀላል ቴክኒኮችን በመጠቀም - ጥሩ ውጤት በትንሽ ኮፒ-መለጠፍ. 🙂
ምንጭ: hab.com