рдорд╣реАрдиреЗ рдкрд╣рд▓реЗ
рдЖрдк рддрдм рд╕реЗ рдЕрдм рддрдХ 6000 рд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рдЙрдкрдпреЛрдЧреА рд╕реБрд╡рд┐рдзрд╛ рдкрд░ рдХрд┐рд╕реА рдХрд╛ рдзреНрдпрд╛рди рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИ рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рд╕реБрд░рд╛рдЧ, рдЬреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреЗ рд╣реИрдВ:
рдЙрдиреНрд╣реЗрдВ рд╕реБрдиреЗрдВ рдФрд░ рдЖрдкрдХреЗ рдЕрдиреБрд░реЛрдз "рд░реЗрд╢рдореА рдЪрд┐рдХрдиреА рд╣реЛ рдЬрд╛рдПрдВрдЧреЗ"ред ЁЯЩВ
рд▓реЗрдХрд┐рди рдЧрдВрднреАрд░рддрд╛ рд╕реЗ, рдХрдИ рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рдЬреЛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрдиреБрд░реЛрдз рдХреЛ рдзреАрдорд╛ рдФрд░ "рднрдХреНрд╖рдХ" рдмрдирд╛рддреА рд╣реИрдВ, рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИрдВ рдФрд░ рдпреЛрдЬрдирд╛ рдХреА рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдбреЗрдЯрд╛ рджреНрд╡рд╛рд░рд╛ рдкрд╣рдЪрд╛рдиреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ.
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЕрдиреБрднрд╡ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддреЗ рд╣реБрдП, рдЕрдкрдиреЗ рджрдо рдкрд░ рдПрдХ рдЕрдиреБрдХреВрд▓рди рд╡рд┐рдХрд▓реНрдк рдХреА рддрд▓рд╛рд╢ рдирд╣реАрдВ рдХрд░рдиреА рд╣реЛрдЧреА - рд╣рдо рдЙрд╕реЗ рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдХреНрдпрд╛ рдХрд╛рд░рдг рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдХреИрд╕реЗ рд╕рдорд╛рдзрд╛рди рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛рдП. рдЬреЛ рд╣рдордиреЗ рдХрд┐рдпрд╛ред
рдЖрдЗрдП рдЗрди рдорд╛рдорд▓реЛрдВ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ - рдЙрдиреНрд╣реЗрдВ рдХреИрд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╡реЗ рдХрд┐рди рд╕рд┐рдлрд╛рд░рд┐рд╢реЛрдВ рдХреА рдУрд░ рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВред
рд╡рд┐рд╖рдп рдореЗрдВ рдмреЗрд╣рддрд░ рддрд▓реНрд▓реАрдирддрд╛ рдХреЗ рд▓рд┐рдП, рдЖрдк рдкрд╣рд▓реЗ рд╕рдВрдмрдВрдзрд┐рдд рдмреНрд▓реЙрдХ рдХреЛ рд╕реБрди рд╕рдХрддреЗ рд╣реИрдВ
#1: рдЗрдВрдбреЗрдХреНрд╕ "рдЕрдВрдбрд░рд╕реЙрд░реНрдЯрд┐рдВрдЧ"
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдХреНрд▓рд╛рдЗрдВрдЯ "рдПрд▓рдПрд▓рд╕реА рдХреЛрд▓реЛрдХреЛрд▓рд┐рдХ" рдХреЗ рд▓рд┐рдП рдЕрдВрддрд┐рдо рдЪрд╛рд▓рд╛рди рджрд┐рдЦрд╛рдПрдВред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> Limit
-> Sort
-> Index [Only] Scan [Backward] | Bitmap Heap Scan
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рд╕реЙрд░реНрдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде рд╡рд┐рд╕реНрддреГрдд рдХрд░реЗрдВ.
рдЙрджрд╛рд╣рд░рдг:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "╤Д╨░╨║╤В╨╛╨▓"
, (random() * 1000)::integer fk_cli; -- 1K ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
CREATE INDEX ON tbl(fk_cli); -- ╨╕╨╜╨┤╨╡╨║╤Б ╨┤╨╗╤П foreign key
SELECT
*
FROM
tbl
WHERE
fk_cli = 1 -- ╨╛╤В╨▒╨╛╤А ╨┐╨╛ ╨║╨╛╨╜╨║╤А╨╡╤В╨╜╨╛╨╣ ╤Б╨▓╤П╨╖╨╕
ORDER BY
pk DESC -- ╤Е╨╛╤В╨╕╨╝ ╨▓╤Б╨╡╨│╨╛ ╨╛╨┤╨╜╤Г "╨┐╨╛╤Б╨╗╨╡╨┤╨╜╤О╤О" ╨╖╨░╨┐╨╕╤Б╤М
LIMIT 1;
рдЖрдк рддреБрд░рдВрдд рдиреЛрдЯрд┐рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЗрдВрдбреЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ 100 рд╕реЗ рдЕрдзрд┐рдХ рд░рд┐рдХреЙрд░реНрдб рдШрдЯрд╛рдП рдЧрдП рдереЗ, рдЬреЛ рддрдм рд╕рднреА рд╕реЙрд░реНрдЯ рдХрд┐рдП рдЧрдП рдереЗ, рдФрд░ рдлрд┐рд░ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдмрдЪрд╛ рдерд╛ред
рд╣рдо рддрдп рдХрд░рддреЗ рд╣реИрдВ:
DROP INDEX tbl_fk_cli_idx;
CREATE INDEX ON tbl(fk_cli, pk DESC); -- ╨┤╨╛╨▒╨░╨▓╨╕╨╗╨╕ ╨║╨╗╤О╤З ╤Б╨╛╤А╤В╨╕╤А╨╛╨▓╨║╨╕
рдРрд╕реЗ рдЖрджрд┐рдо рдирдореВрдиреЗ рдкрд░ рднреА - 8.5x рддреЗрдЬ рдФрд░ 33x рдХрдо рдкрдврд╝рддрд╛ рд╣реИ. рдкреНрд░рднрд╛рд╡ рд╕реНрдкрд╖реНрдЯ рд╣реЛрдЧрд╛, рдЖрдкрдХреЗ рдкрд╛рд╕ рдкреНрд░рддреНрдпреЗрдХ рдореВрд▓реНрдп рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ "рддрдереНрдп" рд╣реЛрдВрдЧреЗред fk
.
рдореИрдВ рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдРрд╕рд╛ рд╕реВрдЪрдХрд╛рдВрдХ "рдЙрдкрд╕рд░реНрдЧ" рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдЬреЛ рдЕрдиреНрдп рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдкрд┐рдЫрд▓реЗ рдПрдХ рд╕реЗ рднреА рдмрджрддрд░ рдирд╣реАрдВ рд╣реИ fk
, рдЬрд╣рд╛рдВ рджреНрд╡рд╛рд░рд╛ рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ pk
рдирд╣реАрдВ рдерд╛ рдФрд░ рдирд╣реАрдВ рд╣реИ (рдЖрдк рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ
# 2: рдЗрдВрдбреЗрдХреНрд╕ рдЪреМрд░рд╛рд╣рд╛ (рдмрд┐рдЯрдореИрдк рдФрд░)
рдХрдм рдХрд░рддрд╛ рд╣реИ
"NJSC Lyutik" рдХреА рдУрд░ рд╕реЗ рд╕рдВрдкрдиреНрди рдХреНрд▓рд╛рдЗрдВрдЯ "LLC Kolocolchik" рдХреЗ рд▓рд┐рдП рд╕рднреА рдЕрдиреБрдмрдВрдз рджрд┐рдЦрд╛рдПрдВред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> BitmapAnd
-> Bitmap Index Scan
-> Bitmap Index Scan
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдмрдирд╛рдПрдБ рд╕рдВрдпреБрдХреНрдд рд╕реВрдЪрдХрд╛рдВрдХ рджреЛрдиреЛрдВ рд╕реНрд░реЛрддреЛрдВ рд╕реЗ рдлрд╝реАрд▓реНрдб рджреНрд╡рд╛рд░рд╛ рдпрд╛ рджреВрд╕рд░реЗ рд╕реЗ рдореМрдЬреВрджрд╛ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВред
рдЙрджрд╛рд╣рд░рдг:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "╤Д╨░╨║╤В╨╛╨▓"
, (random() * 100)::integer fk_org -- 100 ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
, (random() * 1000)::integer fk_cli; -- 1K ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
CREATE INDEX ON tbl(fk_org); -- ╨╕╨╜╨┤╨╡╨║╤Б ╨┤╨╗╤П foreign key
CREATE INDEX ON tbl(fk_cli); -- ╨╕╨╜╨┤╨╡╨║╤Б ╨┤╨╗╤П foreign key
SELECT
*
FROM
tbl
WHERE
(fk_org, fk_cli) = (1, 999); -- ╨╛╤В╨▒╨╛╤А ╨┐╨╛ ╨║╨╛╨╜╨║╤А╨╡╤В╨╜╨╛╨╣ ╨┐╨░╤А╨╡
рд╣рдо рддрдп рдХрд░рддреЗ рд╣реИрдВ:
DROP INDEX tbl_fk_org_idx;
CREATE INDEX ON tbl(fk_org, fk_cli);
рдпрд╣рд╛рдБ рд▓рд╛рдн рдЫреЛрдЯрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдмрд┐рдЯрдореИрдк рд╣реАрдк рд╕реНрдХреИрди рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдХрд╛рдлреА рдкреНрд░рднрд╛рд╡реА рд╣реИред рд▓реЗрдХрд┐рди рд╡реИрд╕реЗ рднреА 7x рддреЗрдЬ рдФрд░ 2.5x рдХрдо рдкрдврд╝рддрд╛ рд╣реИ.
#3: рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рд╕рдВрдпреЛрдЬрди (рдмрд┐рдЯрдореИрдкрдСрд░)
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдореЗрдВ рд╕реНрд╡рдпрдВ рдХреЗ рд╕рд╛рде рдкрд╣рд▓реЗ 20 рд╕рдмрд╕реЗ рдкреБрд░рд╛рдиреЗ "рд╕реНрд╡рдпрдВ" рдпрд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЕрд╕рд╛рдЗрди рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рдЕрдиреБрд░реЛрдз рджрд┐рдЦрд╛рдПрдВред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> BitmapOr
-> Bitmap Index Scan
-> Bitmap Index Scan
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдШ [рд╕рднреА] рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд┐рддрд┐ рдпрд╛ рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП рдЙрдкрд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
рдЙрджрд╛рд╣рд░рдг:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "╤Д╨░╨║╤В╨╛╨▓"
, CASE
WHEN random() < 1::real/16 THEN NULL -- ╤Б ╨▓╨╡╤А╨╛╤П╤В╨╜╨╛╤Б╤В╤М╤О 1:16 ╨╖╨░╨┐╨╕╤Б╤М "╨╜╨╕╤З╤М╤П"
ELSE (random() * 100)::integer -- 100 ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
END fk_own;
CREATE INDEX ON tbl(fk_own, pk); -- ╨╕╨╜╨┤╨╡╨║╤Б ╤Б "╨▓╤А╨╛╨┤╨╡ ╨║╨░╨║ ╨┐╨╛╨┤╤Е╨╛╨┤╤П╤Й╨╡╨╣" ╤Б╨╛╤А╤В╨╕╤А╨╛╨▓╨║╨╛╨╣
SELECT
*
FROM
tbl
WHERE
fk_own = 1 OR -- ╤Б╨▓╨╛╨╕
fk_own IS NULL -- ... ╨╕╨╗╨╕ "╨╜╨╕╤З╤М╨╕"
ORDER BY
pk
, (fk_own = 1) DESC -- ╤Б╨╜╨░╤З╨░╨╗╨░ "╤Б╨▓╨╛╨╕"
LIMIT 20;
рд╣рдо рддрдп рдХрд░рддреЗ рд╣реИрдВ:
(
SELECT
*
FROM
tbl
WHERE
fk_own = 1 -- ╤Б╨╜╨░╤З╨░╨╗╨░ "╤Б╨▓╨╛╨╕" 20
ORDER BY
pk
LIMIT 20
)
UNION ALL
(
SELECT
*
FROM
tbl
WHERE
fk_own IS NULL -- ╨┐╨╛╤В╨╛╨╝ "╨╜╨╕╤З╤М╨╕" 20
ORDER BY
pk
LIMIT 20
)
LIMIT 20; -- ╨╜╨╛ ╨▓╤Б╨╡╨│╨╛ - 20, ╨▒╨╛╨╗╤М╤И╨╡ ╨╕ ╨╜╨╡ ╨╜╨░╨┤╨╛
рд╣рдордиреЗ рдЗрд╕ рддрдереНрдп рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдпрд╛ рдХрд┐ рдкрд╣рд▓реЗ рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рднреА 20 рдЖрд╡рд╢реНрдпрдХ рд░рд┐рдХреЙрд░реНрдб рддреБрд░рдВрдд рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдЧрдП рдереЗ, рдЗрд╕рд▓рд┐рдП рджреВрд╕рд░рд╛, рдЕрдзрд┐рдХ "рдорд╣рдВрдЧреЗ" рдмрд┐рдЯрдореИрдк рд╣реАрдк рд╕реНрдХреИрди рдХреЗ рд╕рд╛рде, рдирд┐рд╖реНрдкрд╛рджрд┐рдд рднреА рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ - рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк 22x рддреЗрдЬ, 44x рдХрдо рдкрдврд╝рддрд╛ рд╣реИ!
рдЗрд╕ рдЕрдиреБрдХреВрд▓рди рдкрджреНрдзрддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдХрд╣рд╛рдиреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд▓реЗрдЦреЛрдВ рдореЗрдВ рдкрдврд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рдПрдВрдЯреАрдкреИрдЯрд░реНрди: рд╣рд╛рдирд┐рдХрд╛рд░рдХ рдЬреЙрдЗрди рдФрд░ рдУрдЖрд░рдПрд╕ ╨╕PostgreSQL Antipatterns: рдирд╛рдо рд╕реЗ рдЦреЛрдЬ рдХреЗ рдкреБрдирд░рд╛рд╡реГрддреНрдд рд╢реЛрдзрди рдХреА рдХрд╣рд╛рдиреА, рдпрд╛ "рдЖрдЧреЗ рдФрд░ рдкреАрдЫреЗ рдХрд╛ рдЕрдиреБрдХреВрд▓рди" .рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рдХрдИ рдЪрд╛рдмрд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЪрдпрди рдХрд╛ рдЖрджреЗрд╢ рджрд┐рдпрд╛ (рдФрд░ рди рдХреЗрд╡рд▓ const / NULL рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреЗ рд▓рд┐рдП) рд▓реЗрдЦ рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╣реИ
рдПрд╕рдХреНрдпреВрдПрд▓ рд╣рд╛рдЙрдЯреЛ: рдХреНрд╡реЗрд░реА рдореЗрдВ рд╕реАрдзреЗ рдереЛрдбрд╝реА рджреЗрд░ рд▓реВрдк рд▓рд┐рдЦреЗрдВ, рдпрд╛ "рдкреНрд░рд╛рдердорд┐рдХ рддреАрди-рддрд░рдлрд╛" .
#4: рд╣рдо рдмрд╣реБрдд рдЬреНрдпрд╛рджрд╛ рдкрдврд╝рддреЗ рд╣реИрдВ
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдпрд╣ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдЖрдк рдХрд┐рд╕реА рдореМрдЬреВрджрд╛ рдЕрдиреБрд░реЛрдз рдореЗрдВ "рджреВрд╕рд░рд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рд╕рдВрд▓рдЧреНрди рдХрд░рдирд╛" рдЪрд╛рд╣рддреЗ рд╣реИрдВред
"рдФрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореЛрддреА рдмрдЯрди рдХреЗ рд╕рд╛рде? " рдлрд┐рд▓реНрдо "рдбрд╛рдпрдордВрдб рд╣реИрдВрдб"
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдкрд░реЛрдХреНрдд рдХрд╛рд░реНрдп рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реБрдП, рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ 20 рд╕рдмрд╕реЗ рдкреБрд░рд╛рдиреЗ "рдорд╣рддреНрд╡рдкреВрд░реНрдг" рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рджрд┐рдЦрд╛рдПрдВ, рднрд▓реЗ рд╣реА рдЙрдирдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдХреБрдЫ рднреА рд╣реЛред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
&& 5 ├Ч rows < RRbF -- ╨╛╤В╤Д╨╕╨╗╤М╤В╤А╨╛╨▓╨░╨╜╨╛ >80% ╨┐╤А╨╛╤З╨╕╤В╨░╨╜╨╜╨╛╨│╨╛
&& loops ├Ч RRbF > 100 -- ╨╕ ╨┐╤А╨╕ ╤Н╤В╨╛╨╝ ╨▒╨╛╨╗╤М╤И╨╡ 100 ╨╖╨░╨┐╨╕╤Б╨╡╨╣ ╤Б╤Г╨╝╨╝╨░╤А╨╜╨╛
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
[рдЕрдзрд┐рдХ] рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрдирд╛рдПрдБ WHERE рдХреНрд▓реЙрдЬ рдХреЗ рд╕рд╛рде рдЗрдВрдбреЗрдХреНрд╕ рдпрд╛ рдЗрдВрдбреЗрдХреНрд╕ рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВред
рдпрджрд┐ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рд╕реНрдерд┐рддрд┐ рдЖрдкрдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП "рд╕реНрдерд┐рд░" рд╣реИ - рдЕрд░реНрдерд╛рдд рд╡рд┐рд╕реНрддрд╛рд░ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдореВрд▓реНрдпреЛрдВ рдХреА рд╕реВрдЪреА - WHERE рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред рдЗрд╕ рд╢реНрд░реЗрдгреА рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдмреВрд▓рд┐рдпрди/рдПрдирдо рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдлрд┐рдЯ рдмреИрдарддреА рд╣реИрдВред
рдЕрдЧрд░ рдЫрд╛рдирдиреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдорд╛рди рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ - рдЬреИрд╕рд╛ рдХрд┐ рдмрд┐рдЯрдореИрдк рдФрд░ рдКрдкрд░ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИред
рдЙрджрд╛рд╣рд░рдг:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "╤Д╨░╨║╤В╨╛╨▓"
, CASE
WHEN random() < 1::real/16 THEN NULL
ELSE (random() * 100)::integer -- 100 ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
END fk_own
, (random() < 1::real/50) critical; -- 1:50, ╤З╤В╨╛ ╨╖╨░╤П╨▓╨║╨░ "╨║╤А╨╕╤В╨╕╤З╨╜╨░╤П"
CREATE INDEX ON tbl(pk);
CREATE INDEX ON tbl(fk_own, pk);
SELECT
*
FROM
tbl
WHERE
critical
ORDER BY
pk
LIMIT 20;
рд╣рдо рддрдп рдХрд░рддреЗ рд╣реИрдВ:
CREATE INDEX ON tbl(pk)
WHERE critical; -- ╨┤╨╛╨▒╨░╨▓╨╕╨╗╨╕ "╤Б╤В╨░╤В╨╕╤З╨╜╨╛╨╡" ╤Г╤Б╨╗╨╛╨▓╨╕╨╡ ╤Д╨╕╨╗╤М╤В╤А╨░╤Ж╨╕╨╕
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпреЛрдЬрдирд╛ рд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЪрд▓реА рдЧрдИ рд╣реИ, рдФрд░ рдЕрдиреБрд░реЛрдз рдмрди рдЧрдпрд╛ рд╣реИ 5 рдЧреБрдирд╛ рддреЗрдЬ.
# 5: рд╡рд┐рд░рд▓ рддрд╛рд▓рд┐рдХрд╛
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдХрд╛рд░реНрдп рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрддрд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдпрд╛рд╕, рдЬрдм рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЕрджреНрдпрддрди / рд╡рд┐рд▓реЛрдкрди рд░рд┐рдХреЙрд░реНрдб рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ "рдореГрдд" рд░рд┐рдХреЙрд░реНрдб рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрдирддреЗ рд╣реИрдВред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
&& loops ├Ч (rows + RRbF) < (shared hit + shared read) ├Ч 8
-- ╨┐╤А╨╛╤З╨╕╤В╨░╨╜╨╛ ╨▒╨╛╨╗╤М╤И╨╡ 1KB ╨╜╨░ ╨║╨░╨╢╨┤╤Г╤О ╨╖╨░╨┐╨╕╤Б╤М
&& shared hit + shared read > 64
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдХрд░реЗрдВ рд╡реИрдХреНрдпреВрдо [рдкреВрд░реНрдг] рдпрд╛ рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдРрд╕реА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рд╕реЗ рдмреБрд▓рд╛рдП рдЬрд╛рдиреЗ рдкрд░ рдЦрд░рд╛рдм рдХреНрд╡реЗрд░реА рд▓реЗрдЖрдЙрдЯ рдХреЗ рдХрд╛рд░рдг рд╣реЛрддреА рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ рдЬрд┐рди рдкрд░ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╣реИ
PostgreSQL Antipatterns: "рдореГрдд" рдХреА рднреАрдбрд╝ рд╕реЗ рд▓рдбрд╝рдирд╛ .рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдпрд╣ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ VACUUM FULL рд╣рдореЗрд╢рд╛ рдорджрдж рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд▓реЗрдЦ рд╕реЗ рдПрд▓реНрдЧреЛрд░рд┐рдердо рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
DBA: рдЬрдм VACUUM рдкрд╛рд╕ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЯреЗрдмрд▓ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВ .
#6: рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ "рдордзреНрдп" рд╕реЗ рдкрдврд╝рдирд╛
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЛрдВрдиреЗ рдереЛрдбрд╝рд╛ рдкрдврд╝рд╛, рдФрд░ рд╕рдм рдХреБрдЫ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЙрдиреНрд╣реЛрдВрдиреЗ рдХрд┐рд╕реА рдХреЛ рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝рд┐рд▓реНрдЯрд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ - рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА, рд╣рдо рдЬрд┐рддрдиреЗ рдкреГрд╖реНрда рдЪрд╛рд╣реЗрдВрдЧреЗ, рдЙрд╕рд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдкреГрд╖реНрда рдкрдврд╝реЗ рдЧрдПред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> Index [Only] Scan [Backward]
&& loops ├Ч (rows + RRbF) < (shared hit + shared read) ├Ч 8
-- ╨┐╤А╨╛╤З╨╕╤В╨░╨╜╨╛ ╨▒╨╛╨╗╤М╤И╨╡ 1KB ╨╜╨░ ╨║╨░╨╢╨┤╤Г╤О ╨╖╨░╨┐╨╕╤Б╤М
&& shared hit + shared read > 64
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдХреНрд╡реЗрд░реА рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рдореБрдЦ рдХреНрд╖реЗрддреНрд░реЛрдВ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ - рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рднрд╛рдЧ рд╕реЗрдЯ рдирд╣реАрдВ рд╣реИ. рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдПрдХ рд╕рдорд╛рди рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди рдЙрдкрд╕рд░реНрдЧ рдлрд╝реАрд▓реНрдб рдХреЗ рдмрд┐рдирд╛, рдпрд╛
рдЙрджрд╛рд╣рд░рдг:
CREATE TABLE tbl AS
SELECT
generate_series(1, 100000) pk -- 100K "╤Д╨░╨║╤В╨╛╨▓"
, (random() * 100)::integer fk_org -- 100 ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
, (random() * 1000)::integer fk_cli; -- 1K ╤А╨░╨╖╨╜╤Л╤Е ╨▓╨╜╨╡╤И╨╜╨╕╤Е ╨║╨╗╤О╤З╨╡╨╣
CREATE INDEX ON tbl(fk_org, fk_cli); -- ╨▓╤Б╨╡ ╨┐╨╛╤З╤В╨╕ ╨║╨░╨║ ╨▓ #2
-- ╤В╨╛╨╗╤М╨║╨╛ ╨▓╨╛╤В ╨╛╤В╨┤╨╡╨╗╤М╨╜╤Л╨╣ ╨╕╨╜╨┤╨╡╨║╤Б ╨┐╨╛ fk_cli ╨╝╤Л ╤Г╨╢╨╡ ╨┐╨╛╤Б╤З╨╕╤В╨░╨╗╨╕ ╨╗╨╕╤И╨╜╨╕╨╝ ╨╕ ╤Г╨┤╨░╨╗╨╕╨╗╨╕
SELECT
*
FROM
tbl
WHERE
fk_cli = 999 -- ╨░ fk_org ╨╜╨╡ ╨╖╨░╨┤╨░╨╜╨╛, ╤Е╨╛╤В╤П ╤Б╤В╨╛╨╕╤В ╨▓ ╨╕╨╜╨┤╨╡╨║╤Б╨╡ ╤А╨░╨╜╤М╤И╨╡
LIMIT 20;
рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рднреА рд╕рдм рдХреБрдЫ рдареАрдХ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рддрд░рд╣ рд╕рдВрджреЗрд╣рд╛рд╕реНрдкрдж - тАЛтАЛрдкреНрд░рддреНрдпреЗрдХ 20 рд░рд┐рдХреЙрд░реНрдб рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдбреЗрдЯрд╛ рдХреЗ 4 рдкреГрд╖реНрда рдШрдЯрд╛рдП рдЬрд╛рдиреЗ рдереЗ, 32KB рдкреНрд░рддрд┐ рд░рд┐рдХреЙрд░реНрдб - рдХреНрдпрд╛ рдпрд╣ рдмреЛрд▓реНрдб рдирд╣реАрдВ рд╣реИ? рд╣рд╛рдВ рдФрд░ рдЗрдВрдбреЗрдХреНрд╕ рдирд╛рдо tbl_fk_org_fk_cli_idx
рд╡рд┐рдЪрд╛рд░ рдХреА рдУрд░ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред
рд╣рдо рддрдп рдХрд░рддреЗ рд╣реИрдВ:
CREATE INDEX ON tbl(fk_cli);
рдЕрдЪрд╛рдирдХ - рдкрдврд╝рдиреЗ рдореЗрдВ 10 рдЧреБрдирд╛ рддреЗрдЬ рдФрд░ 4 рдЧреБрдирд╛ рдХрдо!
рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рдЕрдХреНрд╖рдо рдЙрдкрдпреЛрдЧ рдХреЗ рдЕрдзрд┐рдХ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрд▓реЗрдЦ рджреЗрдЦреЗрдВ
рдбреАрдмреАрдП: рдмреЗрдХрд╛рд░ рдЗрдВрдбреЗрдХреНрд╕ рдЦреЛрдЬреЗрдВ .
#7: рд╕реАрдЯреАрдИ ├Ч рд╕реАрдЯреАрдИ
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдЕрдиреБрд░реЛрдз рдореЗрдВ "рд╡рд╕рд╛" рд╕реАрдЯреАрдИ рд╕реНрдХреЛрд░ рдХрд┐рдпрд╛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рд╕реЗ, рдФрд░ рдлрд┐рд░ рдЙрдирдХреЗ рдмреАрдЪ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ JOIN
.
рдорд╛рдорд▓рд╛ v12 рд╕реЗ рдиреАрдЪреЗ рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдпрд╛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИ WITH MATERIALIZED
.
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> CTE Scan
&& loops > 10
&& loops ├Ч (rows + RRbF) > 10000
-- ╤Б╨╗╨╕╤И╨║╨╛╨╝ ╨▒╨╛╨╗╤М╤И╨╛╨╡ ╨┤╨╡╨║╨░╤А╤В╨╛╨▓╨╛ ╨┐╤А╨╛╨╕╨╖╨▓╨╡╨┤╨╡╨╜╨╕╨╡ CTE
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдЕрдиреБрд░реЛрдз рдХрд╛ рд╕рд╛рд╡рдзрд╛рдиреАрдкреВрд░реНрд╡рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВ
# 8: рдбрд┐рд╕реНрдХ рдкрд░ рд╕реНрд╡реИрдк рдХрд░реЗрдВ (рдЕрд╕реНрдерд╛рдпреА рд░реВрдк рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛)
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХреА рдПрдХ рдмрд╛рд░ рдХреА рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ (рд╕реЙрд░реНрдЯрд┐рдВрдЧ рдпрд╛ рдпреВрдирд┐рдХрд╛рдЗрдЬреЗрд╢рди) рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рдВрдЯрд┐рдд рдореЗрдореЛрд░реА рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> *
&& temp written > 0
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдпрджрд┐ рдСрдкрд░реЗрд╢рди рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдореЗрдореЛрд░реА рдХреА рдорд╛рддреНрд░рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕реЗрдЯ рдорд╛рди рд╕реЗ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ SET [LOCAL]
рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЕрдиреБрд░реЛрдз/рд▓реЗрдирджреЗрди рдХреЗ рд▓рд┐рдПред
рдЙрджрд╛рд╣рд░рдг:
SHOW work_mem;
-- "16MB"
SELECT
random()
FROM
generate_series(1, 1000000)
ORDER BY
1;
рд╣рдо рддрдп рдХрд░рддреЗ рд╣реИрдВ:
SET work_mem = '128MB'; -- ╨┐╨╡╤А╨╡╨┤ ╨▓╤Л╨┐╨╛╨╗╨╜╨╡╨╜╨╕╨╡╨╝ ╨╖╨░╨┐╤А╨╛╤Б╨░
рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдХреЗрд╡рд▓ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдбрд┐рд╕реНрдХ рдХрд╛ рдирд╣реАрдВ, рддреЛ рдХреНрд╡реЗрд░реА рдмрд╣реБрдд рддреЗрдЬ рд╣реЛрдЧреАред рд╡рд╣реАрдВ, рд▓реЛрдб рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдПрдЪрдбреАрдбреА рд╕реЗ рднреА рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рдмрд╣реБрдд рд╕рд╛рд░реА рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рд╕реЗ рд╣рдореЗрд╢рд╛ рдХрд╛рдо рдирд╣реАрдВ рдЪрд▓реЗрдЧрд╛ - рдпрд╣ рдмрд╕ рд╕рднреА рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
#9: рдЕрдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЖрдБрдХрдбрд╝реЗ
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдмреЗрд╕ рдореЗрдВ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдбрд╛рд▓рд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЙрдирдХреЗ рдкрд╛рд╕ рдЗрд╕реЗ рдЪрд▓рд╛рдиреЗ рдХрд╛ рд╕рдордп рдирд╣реАрдВ рдерд╛ ANALYZE
.
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> Seq Scan | Bitmap Heap Scan | Index [Only] Scan [Backward]
&& ratio >> 10
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рд╣реА рдЦрд░реНрдЪ рдХрд░реЗрдВ ANALYZE
.
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
PostgreSQL Antipatterns: рдЖрдБрдХрдбрд╝реЗ рд╣рд░ рдЪреАрдЬ рдХреЗ рдкреНрд░рдореБрдЦ рд╣реИрдВ .
#10: "рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рдЧрдпрд╛"
рдХрдм рдХрд░рддрд╛ рд╣реИ
рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЙрдХ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рдерд╛, рдпрд╛ рдкрд░реНрдпрд╛рдкреНрдд CPU/рд╣рд╛рдЗрдкрд░рд╡рд╛рдЗрдЬрд╝рд░ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрд╕рд╛рдзрди рдирд╣реАрдВ рдереЗред
рдХреИрд╕реЗ рдкрд╣рдЪрд╛рдиреЗрдВ
-> *
&& (shared hit / 8K) + (shared read / 1K) < time / 1000
-- RAM hit = 64MB/s, HDD read = 8MB/s
&& time > 100ms -- ╤З╨╕╤В╨░╨╗╨╕ ╨╝╨░╨╗╨╛, ╨╜╨╛ ╤Б╨╗╨╕╤И╨║╨╛╨╝ ╨┤╨╛╨╗╨│╨╛
рдЕрдиреБрд╢рдВрд╕рд╛рдПрдБ
рдПрдХ рдмрд╛рд╣рд░реА рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ рдирд┐рдЧрд░рд╛рдиреА рдкреНрд░рдгрд╛рд▓реА рдЕрд╡рд░реБрджреНрдз рдпрд╛ рдЕрд╕рд╛рдорд╛рдиреНрдп рд╕рдВрд╕рд╛рдзрди рдЦрдкрдд рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ред рд╣рдо рд╕реИрдХрдбрд╝реЛрдВ рд╕рд░реНрд╡рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЖрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рдЕрдкрдиреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрд╣рд▓реЗ рд╣реА рдмрд╛рдд рдХрд░ рдЪреБрдХреЗ рд╣реИрдВред
рд╕реНрд░реЛрдд: www.habr.com