DBA: рдмреЗрдХрд╛рд░ рд╕реВрдЪрдХрд╛рдВрдХ рдЦреЛрдЬреЗрдВ

рдореИрдВ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЖрддрд╛ рд╣реВрдВ рдЬрд╣рд╛рдВ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдХреНрд╕реЗрд▓ рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдПрдХ рд╕реНрд╡рд┐рд╕ рдЪрд╛рдХреВ рд╣реИ рдЬреЛ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд░реВрдк рд╕реЗ рдХрд┐рд╕реА рднреА рдкреНрд░рд╢реНрди рд╕рдорд╕реНрдпрд╛ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рдпрд╣ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдХреБрдЫ рдирдП рд╕реВрдЪрдХрд╛рдВрдХ рдЬреЛрдбрд╝рдиреЗ рдпрд╛ рдореМрдЬреВрджрд╛ рдПрдХ рдореЗрдВ рдХрд╣реАрдВ рди рдХрд╣реАрдВ рдХреНрд╖реЗрддреНрд░ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ , рдФрд░ рдлрд┐рд░ (рдЬрд╛рджреВ-рдЬрд╛рджреВ!) рд╕рднреА рдкреНрд░рд╢реНрди рдЗрд╕ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдкреНрд░рднрд╛рд╡реА рдврдВрдЧ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рдпрд╛ рддреЛ рд╡реЗ, рдпрд╛ рдирд╣реАрдВ, рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдпрд╛ рд╕рднреА рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рджреВрд╕рд░реЗ, рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗрд╡рд▓ рд▓реЗрдЦрди рдХреЗ рджреМрд░рд╛рди рдкреНрд░рджрд░реНрд╢рди рдХреЗ рдореБрджреНрджреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗред

рдЕрдХреНрд╕рд░, рдРрд╕реА рд╕реНрдерд┐рддрд┐рдпрд╛рдБ "рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЪрд▓рдиреЗ" рд╡рд╛рд▓реЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рд╣реЛрддреА рд╣реИрдВ, рдЬрдм рдХрд╕реНрдЯрдо рдЙрддреНрдкрд╛рдж рдХреЛ "рдПрдХ рдмрд╛рд░ рд▓рд┐рдЦреЗ, рджрд┐рдП рдЧрдП, рднреБрд▓рд╛ рджрд┐рдП рдЧрдП" рдореЙрдбрд▓ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИрд▓рдВрдмреЗ рдЬреАрд╡рди рдЪрдХреНрд░ рдХреЗ рд╕рд╛рде рд╕реЗрд╡рд╛ ред

рд╕реБрдзрд╛рд░ рдХрдИ рд╡рд┐рддрд░рд┐рдд рдЯреАрдореЛрдВ рдХреА рддрд╛рдХрддреЛрдВ рджреНрд╡рд╛рд░рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрдд рд╣реЛрддреЗ рд╣реИрдВ, рдЬреЛ рди рдХреЗрд╡рд▓ рдЕрдВрддрд░рд┐рдХреНрд╖ рдореЗрдВ рдмрд▓реНрдХрд┐ рд╕рдордп рдореЗрдВ рднреА рд╡рд┐рддрд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдФрд░ рдлрд┐рд░, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдкреВрд░реЗ рдЗрддрд┐рд╣рд╛рд╕ рдпрд╛ рдЗрд╕рдХреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд▓рд╛рдЧреВ рд╡рд┐рддрд░рдг рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реБрдП, рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЗ рд╕рд╛рде "рдЧрдбрд╝рдмрдбрд╝ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ"ред рд▓реЗрдХрд┐рди рдХрдЯреМрддреА рдХреЗ рддрд╣рдд рд╡рд┐рдЪрд╛рд░ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдЕрдиреБрд░реЛрдз рдЖрдкрдХреЛ рдЕрдЧреНрд░рд┐рдо рдореЗрдВ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рднрд╛рдЧ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рдиреЗ рдФрд░ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ:

  • рдЕрдкреНрд░рдпреБрдХреНрдд рдЗрдВрдбреЗрдХреНрд╕
  • рдЙрдкрд╕рд░реНрдЧ "рдХреНрд▓реЛрди"
  • рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк "рдмреАрдЪ рдореЗрдВ"
  • рдЗрдВрдбреЗрдХреНрд╕рдмрд▓ рдмреВрд▓рд┐рдпрди
  • рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рд╕рд░рдгрд┐рдпрд╛рдБ
  • рдЕрд╢рдХреНрдд рдХрдЪрд░рд╛

рд╕рдмрд╕реЗ рд╕рд░рд▓ рдмрд╛рдд рдЙрди рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХреЛ рдвреВрдВрдврдирд╛ рд╣реИ рдЬрд┐рдирдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдХреБрд▓ рднреА рдкрд╛рд╕ рдирд╣реАрдВ рдереЗ ред рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рдХрд┐ рдЖрдБрдХрдбрд╝реЗ ( pg_stat_reset()) рд░реАрд╕реЗрдЯ рдмрд╣реБрдд рдкрд╣рд▓реЗ рд╣реЛ рдЪреБрдХреЗ рд╣реИрдВ, рдФрд░ рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП "рд╢рд╛рдпрдж рд╣реА рдХрднреА, рд▓реЗрдХрд┐рди рдЙрдкрдпреБрдХреНрдд" рдХреЛ рд╣рдЯрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╣рдо рд╕рд┐рд╕реНрдЯрдо рджреГрд╢реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ pg_stat_user_indexes:

SELECT * FROM pg_stat_user_indexes WHERE idx_scan = 0;

рд▓реЗрдХрд┐рди рднрд▓реЗ рд╣реА рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рдЪрдпрди рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдЖрдкрдХреЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓ рд╣реИред

рдХреМрди рд╕реЗ рд╕реВрдЪрдХрд╛рдВрдХ рдЙрдкрдпреБрдХреНрдд рд╣реИрдВ [рдирд╣реАрдВ]


рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХреБрдЫ рдкреНрд░рд╢реНрди "рдЗрдВрдбреЗрдХреНрд╕ рдкрд░ рдЦрд░рд╛рдм рдХреНрдпреЛрдВ рд╣реИрдВ", рдЖрдЗрдП рдПрдХ рдирд┐рдпрдорд┐рдд btree рдЗрдВрдбреЗрдХреНрд╕ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддреЗ рд╣реИрдВ - рдкреНрд░рдХреГрддрд┐ рдореЗрдВ рд╕рдмрд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рдЙрджрд╛рд╣рд░рдгред рдХрд┐рд╕реА рдПрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рдВрдХреЗрдд рдЖрдорддреМрд░ рдкрд░ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдкреИрджрд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЙрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рдЬреЛрдбрд╝реА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рдордЧреНрд░ рдкрд░ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИрдВред

рдПрдХ рдЕрддреНрдпрдВрдд рд╕рд░рд▓реАрдХреГрдд рддрд░реАрдХрд╛, рдЬреИрд╕рд╛ рдХрд┐ рдЗрд╕рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдПрдХ "рд╕реНрддрд░рд┐рдд рдХреЗрдХ" рд╣реИ, рдЬрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рдкрд░рдд рдореЗрдВ рдЖрджреЗрд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд╖реЗрддреНрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкреЗрдбрд╝реЛрдВ рдХрд╛ рдЖрджреЗрд╢ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред



рдЕрдм рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдХреНрд╖реЗрддреНрд░ рдП рдиреЗ рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рдЖрджреЗрд╢ рджрд┐рдпрд╛, рдФрд░ рдмреА - рдХреЗрд╡рд▓ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореВрд▓реНрдп рдП рдХреЗ рднреАрддрд░ ред рдЖрдЗрдП рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рд╢реНрдиреЛрдВ рдореЗрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ, рдФрд░ рд╡реЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ "рдХреИрд╕реЗ" рдЪрд▓реЗрдВрдЧреЗред

рдЕрдЪреНрдЫреА: рдЙрдкрд╕рд░реНрдЧ рд╕реНрдерд┐рддрд┐


рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕реВрдЪрдХрд╛рдВрдХ btree(A, B)рдореЗрдВ "рд╕рдмрдЗрдВрдбреЗрдХреНрд╕" рд╢рд╛рдорд┐рд▓ рд╣реИ btree(A)ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдиреАрдЪреЗ рд╡рд░реНрдгрд┐рдд рд╕рднреА рдирд┐рдпрдо рдХрд┐рд╕реА рднреА рдЙрдкрд╕рд░реНрдЧ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред

рдпрджрд┐ рдЖрдк рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╕реВрдЪрдХрд╛рдВрдХ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ btree(A, B, C)- рдЖрдк рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдкрдХрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ "рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ":

  • btree(A, B, C)
  • btree(A, B)
  • btree(A)

рдФрд░ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЙрдкрд╕рд░реНрдЧ рд╕реВрдЪрдХрд╛рдВрдХ рдХреА "рднреМрддрд┐рдХ" рдЙрдкрд╕реНрдерд┐рддрд┐ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдмреЗрдорд╛рдиреА рд╣реИред рдЖрдЦрд┐рд░рдХрд╛рд░, рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рдЬрд┐рддрдирд╛ рдЕрдзрд┐рдХ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ - рдЙрддрдирд╛ рд╣реА рдЦрд░рд╛рдм рд╣реЛрддрд╛ рд╣реИ , рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ PostgreSQL рдХреЗ рд▓рд┐рдП рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ рд▓рд┐рдЦреЗрдВ рдкреНрд░рд╡рд░реНрдзрди - рдЙрдмреЗрд░ рдиреЗ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╢рд┐рдХрд╛рдпрдд рдХреА (рдФрд░ рдпрд╣рд╛рдВ рдЖрдк рдЙрдирдХреЗ рджрд╛рд╡реЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ )ред

рдФрд░ рдЕрдЧрд░ рдХреБрдЫ рдЖрдзрд╛рд░ рдХреЛ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд░рд╣рдиреЗ рд╕реЗ рд░реЛрдХрддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдЦреЛрдЬрдиреЗ рдФрд░ рдЗрд╕реЗ рдЦрддреНрдо рдХрд░рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИред рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ:

CREATE TABLE tbl(A integer, B integer, val integer);
CREATE INDEX ON tbl(A, B)
  WHERE val IS NULL;
CREATE INDEX ON tbl(A) --  #1
  WHERE val IS NULL;
CREATE INDEX ON tbl(A, B, val);
CREATE INDEX ON tbl(A); --  #2

рдЙрдкрд╕рд░реНрдЧ рд╕реВрдЪрдХрд╛рдВрдХ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА
WITH sch AS (
  SELECT
    'public'::text sch -- schema
)
, def AS (
  SELECT
    clr.relname nmt
  , cli.relname nmi
  , pg_get_indexdef(cli.oid) def
  , cli.oid clioid
  , clr
  , cli
  , idx
, (
    SELECT
      array_agg(T::text ORDER BY f.i)
    FROM
      (
        SELECT
          clr.oid rel
        , i
        , idx.indkey[i] ik
        FROM
          generate_subscripts(idx.indkey, 1) i
      ) f
    JOIN
      pg_attribute T
        ON (T.attrelid, T.attnum) = (f.rel, f.ik)
  ) fld$
  FROM
    pg_class clr
  JOIN
    pg_index idx
      ON idx.indrelid = clr.oid AND
      idx.indexprs IS NULL
  JOIN
    pg_class cli
      ON cli.oid = idx.indexrelid
  JOIN
    pg_namespace nsp
      ON nsp.oid = cli.relnamespace AND
      nsp.nspname = (TABLE sch)
  WHERE
    NOT idx.indisunique AND
    idx.indisready AND
    idx.indisvalid
  ORDER BY
    clr.relname, cli.relname
)
, fld AS (
  SELECT
    *
  , ARRAY(
      SELECT
        (att::pg_attribute).attname
      FROM
        unnest(fld$) att
    ) nmf$
  , ARRAY(
      SELECT
        (
          SELECT
            typname
          FROM
            pg_type
          WHERE
            oid = (att::pg_attribute).atttypid
        )
      FROM
        unnest(fld$) att
    ) tpf$
  , CASE
      WHEN def ~ ' WHERE ' THEN regexp_replace(def, E'.* WHERE ', '')
    END wh
  FROM
    def
)
, pre AS (
  SELECT
    nmt
  , wh
  , nmf$
  , tpf$
  , nmi
  , def
  FROM
    fld
  ORDER BY
    1, 2, 3
)
SELECT DISTINCT
  Y.*
FROM
  pre X
JOIN
  pre Y
    ON Y.nmi <> X.nmi AND
    (Y.nmt, Y.wh) IS NOT DISTINCT FROM (X.nmt, X.wh) AND
    (
      Y.nmf$[1:array_length(X.nmf$, 1)] = X.nmf$ OR
      X.nmf$[1:array_length(Y.nmf$, 1)] = Y.nmf$
    )
ORDER BY
  1, 2, 3;

рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рдЖрдкрдХреЛ рдПрдХ рдЦрд╛рд▓реА рдЪрдпрди рдорд┐рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рджреЗрдЦреЛ - рдпреЗ рд╣рдорд╛рд░реЗ рд╕рдВрджрд┐рдЧреНрдз рд╕реВрдЪрдХрд╛рдВрдХ рд╕рдореВрд╣ рд╣реИрдВ:

nmt | wh            | nmf$      | tpf$             | nmi             | def
---------------------------------------------------------------------------------------
tbl | (val IS NULL) | {a}       | {int4}           | tbl_a_idx       | CREATE INDEX ...
tbl | (val IS NULL) | {a,b}     | {int4,int4}      | tbl_a_b_idx     | CREATE INDEX ...
tbl |               | {a}       | {int4}           | tbl_a_idx1      | CREATE INDEX ...
tbl |               | {a,b,val} | {int4,int4,int4} | tbl_a_b_val_idx | CREATE INDEX ...

рдлрд┐рд░ рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдпрдВ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЫреЛрдЯреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рдерд╛ рдпрд╛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рдереАред

рдЕрдЪреНрдЫрд╛: рдЕрдВрддрд┐рдо рдХреНрд╖реЗрддреНрд░ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рднреА рд╕реНрдерд┐рд░рд╛рдВрдХ


рдпрджрд┐ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдорд╛рди, рдЕрдВрддрд┐рдо рдХреЛ рдЫреЛрдбрд╝рдХрд░, рд╕реНрдерд┐рд░рд╛рдВрдХ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ (рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрд╣ рдлрд╝реАрд▓реНрдб рдП рд╣реИ), рддреЛ рд╕реВрдЪрдХрд╛рдВрдХ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЕрдВрддрд┐рдо рдлрд╝реАрд▓реНрдб рдХрд╛ рдорд╛рди рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдирд┐рд░рдВрддрд░, рдЕрд╕рдорд╛рдирддрд╛, рдЕрдВрддрд░рд╛рд▓, рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдбрд╛рдпрд▓ рдХрд░рдирд╛ IN (...)рдпрд╛ = ANY(...)ред рдФрд░ рдЗрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рднреА рдЗрд╕реЗ рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред



  • WHERE A = constA AND B [op] constB / = ANY(...) / IN (...)
    op : { =, >, >=, <, <= }
  • WHERE A = constA AND B BETWEEN constB1 AND constB2
  • WHERE A = constA ORDER BY B

рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдЙрдкрд╕рд░реНрдЧ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛:

  • WHERE A [op] const / = ANY(...) / IN (...)
    op : { =, >, >=, <, <= }
  • WHERE A BETWEEN const1 AND const2
  • ORDER BY A
  • WHERE (A, B) [op] (constA, constB) / = ANY(...) / IN (...)
    op : { =, >, >=, <, <= }
  • ORDER BY A, B

рдЦрд░рд╛рдм: "рдкрд░рдд" рдХреА рдкреВрд░реА рдЦреЛрдЬ


рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рднрд╛рдЧ рдХреЗ рд╕рд╛рде, рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдЖрдВрджреЛрд▓рди рдХреА рдПрдХрдорд╛рддреНрд░ рдЧрдгрдирд╛ "рдкрд░рддреЛрдВ" рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рд╕рднреА рдореВрд▓реНрдпреЛрдВ рдХреА рдПрдХ рдкреВрд░реНрдг рдЧрдгрдирд╛ рдмрди рдЬрд╛рддреА рд╣реИ ред рдпрд╣ рднрд╛рдЧреНрдпрд╢рд╛рд▓реА рд╣реИ рдпрджрд┐ рдРрд╕реЗ рдореВрд▓реНрдпреЛрдВ рдХреА рдПрдХрддрд╛ рд╣реИ - рдФрд░ рдпрджрд┐ рд╣рдЬрд╛рд░реЛрдВ рд╣реИрдВ рддреЛ? ..

рдЖрдорддреМрд░ рдкрд░ рдРрд╕реА рд╕рдорд╕реНрдпрд╛ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ рдпрджрд┐ рдХреНрд╡реЗрд░реА рдореЗрдВ рдЕрд╕рдорд╛рдирддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ , рддреЛ рд╢рд░реНрдд рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдирд╣реАрдВ рдХрд░рддреА рд╣реИ рдЬреЛ рд╕реВрдЪрдХрд╛рдВрдХ рдХреНрд░рдо рдореЗрдВ рдкрд┐рдЫрд▓реЗ рд╣реИрдВ рдпрд╛ рдЗрд╕ рдХреНрд░рдо рдХреЛ рдЫрдБрдЯрд╛рдИ рдХреЗ рд╕рд╛рде рдЙрд▓реНрд▓рдВрдШрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред

  • WHERE A <> const
  • WHERE B [op] const / = ANY(...) / IN (...)
  • ORDER BY B
  • ORDER BY B, A

рдЦрд░рд╛рдм: рдЕрдВрддрд░рд╛рд▓ рдпрд╛ рд╕реЗрдЯ рдЕрдВрддрд┐рдо рдлрд╝реАрд▓реНрдб рдореЗрдВ рдирд╣реАрдВ рд╣реИ


рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ - рдпрджрд┐ рдЖрдкрдХреЛ рдХреБрдЫ рдордзреНрдпрд╡рд░реНрддреА "рдкрд░рдд" рдкрд░ рдХрдИ рдорд╛рди рдпрд╛ рдЙрдирдХреА рд╕реАрдорд╛ рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ "рдЧрд╣рд░реА" рдЭреВрда рдмреЛрд▓рдиреЗ рд╡рд╛рд▓реЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рджреНрд╡рд╛рд░рд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рдпрд╛ рд╕реЙрд░реНрдЯ рдХрд░реЗрдВ, рддреЛ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рдмреАрдЪ рдореЗрдВ "рдЕрджреНрд╡рд┐рддреАрдп рдорд╛рди" рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реЛрдиреЗ рдкрд░ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛрдВрдЧреАред рдорд╣рд╛рдиред

  • WHERE A BETWEEN constA1 AND constA2 AND B BETWEEN constB1 AND constB2
  • WHERE A = ANY(...) AND B = const
  • WHERE A = ANY(...) ORDER BY B
  • WHERE A = ANY(...) AND B = ANY(...)

рдЦрд░рд╛рдм: рдХреНрд╖реЗрддреНрд░ рдХреЗ рдмрдЬрд╛рдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐


рдХрднреА-рдХрднреА рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдЕрдирдЬрд╛рдиреЗ рдореЗрдВ рдПрдХ рдХреЙрд▓рдо рдХреЛ рдХрд┐рд╕реА рдФрд░ рдЪреАрдЬрд╝ рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ - рдХреБрдЫ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЗрдВрдбреЗрдХреНрд╕ рдирд╣реАрдВ рд╣реИред рдпрд╣ рд╡рд╛рдВрдЫрд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╕реЗ рдПрдХ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛рдХрд░ рдпрд╛ рдЙрд▓рдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рдХреЗ рддрдп рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

  • WHERE A - const1 [op] const2
    рдареАрдХ рдХрд░: WHERE A [op] const1 + const2
  • WHERE A::typeOfConst = const
    рдареАрдХ рдХрд░: WHERE A = const::typeOfA

рд╣рдо рдЦреЗрддреЛрдВ рдХреА рдХрд╛рд░реНрдбрд┐рдиреИрд▓рд┐рдЯреА рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реИрдВ


рдорд╛рди рд▓реАрдЬрд┐рдП рдЖрдк рдПрдХ рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рдЬрд░реВрд░рдд рд╣реИ (A, B), рдФрд░ рдЖрдк рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХреЗрд╡рд▓ рд╕рдорд╛рдирддрд╛ рд╕реЗ рдЪреБрдиреЗрдВ : (A, B) = (constA, constB)ред рд╣реИрд╢ рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрджрд░реНрд╢ рд╣реЛрдЧрд╛ , рд▓реЗрдХрд┐рди ... рдРрд╕реЗ рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рдиреЙрди-рдЬрд░реНрдирд▓рд┐рдВрдЧ (рд╡рд╛рд▓ рд▓реЙрдЧрд┐рдВрдЧ) рдХреЗ рдЕрд▓рд╛рд╡рд╛ рд╕рдВрд╕реНрдХрд░рдг 10 рддрдХ, рд╡реЗ рдХрдИ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рднреА рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:

CREATE INDEX ON tbl USING hash(A, B);
-- ERROR:  access method "hash" does not support multicolumn indexes

рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЖрдкрдиреЗ btree рдХреЛ рдЪреБрдирд╛ рд╣реИред рддреЛ рдЗрд╕рдореЗрдВ рдХреЙрд▓рдо рдХреА рд╡реНрдпрд╡рд╕реНрдерд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИ - (A, B)рдпрд╛ (B, A)? рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рдХреЙрд▓рдо рдореЗрдВ рдбреЗрдЯрд╛ рдХреА рдХрд╛рд░реНрдбрд┐рдиреИрд▓рд┐рдЯреА рдХреЗ рд░реВрдк рдореЗрдВ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ - рдЕрд░реНрдерд╛рдд, рдЗрд╕рдореЗрдВ рдХрд┐рддрдиреЗ рдЕрдиреВрдареЗ рдореВрд▓реНрдп рд╣реИрдВред

рдЖрдЗрдП рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ A = {1,2}, B = {1,2,3,4}, рдФрд░ рджреЛрдиреЛрдВ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рдЯреНрд░реА рдЖрд░реЗрдЦ рдмрдирд╛рдПрдВ:



рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЬрд┐рд╕ рдкреЗрдбрд╝ рдХреЛ рд╣рдо рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЙрд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рдЗрдВрдбреЗрдХреНрд╕ рдореЗрдВ рдПрдХ рдкреЗрдЬ рд╣реИред рдФрд░ рдЬрд┐рддрдиреЗ рдЕрдзрд┐рдХ рд╣реЛрдВрдЧреЗ, рдЙрддрдирд╛ рдЕрдзрд┐рдХ рдбрд┐рд╕реНрдХ рд╕реНрдерд╛рди рд╕реВрдЪрдХрд╛рдВрдХ рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд▓реЗрдЧрд╛, рдЗрд╕реЗ рдкрдврд╝рдиреЗ рдореЗрдВ рдЬрд┐рддрдирд╛ рдЕрдзрд┐рдХ рд╕рдордп рд▓рдЧреЗрдЧрд╛ред

рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╡рд┐рдХрд▓реНрдк (A, B)рдореЗрдВ 10 рдиреЛрдб рд╣реИрдВ, рдФрд░ (B, A)- 12. рдпрд╣реА рд╣реИ, "рдлрд╝реАрд▓реНрдб" рдХреЛ рдХреБрдЫ рдЕрдиреВрдареЗ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде "рдкрд╣рд▓реЗ" рдХреЗ рд░реВрдк рдореЗрдВ рдбрд╛рд▓рдирд╛ рдЕрдзрд┐рдХ рд▓рд╛рднрджрд╛рдпрдХ рд╣реИ ред

рдмреБрд░рд╛: рдПрдХ рдмрд╣реБрдд рдХреБрдЫ рдФрд░ рдЬрдЧрд╣ рд╕реЗ рдмрд╛рд╣рд░ (рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк "рдмреАрдЪ рдореЗрдВ")


рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ рдпрд╣ рд╣рдореЗрд╢рд╛ рд╕рдВрджреЗрд╣рд╛рд╕реНрдкрдж рд▓рдЧрддрд╛ рд╣реИ рдЕрдЧрд░ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк [tz] рдЬреИрд╕реА рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдмрдбрд╝реА рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓рддрд╛ рд╡рд╛рд▓рд╛ рдХреНрд╖реЗрддреНрд░ рдЖрдкрдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдЕрдВрддрд┐рдо рдирд╣реАрдВ рд╣реИ ред рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдлрд╝реАрд▓реНрдб рдХреЗ рдорд╛рди рдПрдХ-рджреВрд╕рд░реЗ рд╕реЗ рдмрдврд╝рддреЗ рд╣реИрдВ, рдФрд░ рдирд┐рдореНрди рд╕реВрдЪрдХрд╛рдВрдХ рдлрд╝реАрд▓реНрдб рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдордп рдмрд┐рдВрджреБ рдкрд░ рдХреЗрд╡рд▓ рдПрдХ рдореВрд▓реНрдп рд╣реЛрддрд╛ рд╣реИред

CREATE TABLE tbl(A integer, B timestamp);
CREATE INDEX ON tbl(A, B);
CREATE INDEX ON tbl(B, A); -- - 



рдЧреИрд░-рдЕрдВрддрд┐рдо рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк [tz] рдЕрдиреБрдХреНрд░рдорд┐рдд рдХреЗ рд▓рд┐рдП рдЦреЛрдЬ рдХреНрд╡реЗрд░реА
WITH sch AS (
  SELECT
    'public'::text sch -- schema
)
, def AS (
  SELECT
    clr.relname nmt
  , cli.relname nmi
  , pg_get_indexdef(cli.oid) def
  , cli.oid clioid
  , clr
  , cli
  , idx
, (
    SELECT
      array_agg(T::text ORDER BY f.i)
    FROM
      (
        SELECT
          clr.oid rel
        , i
        , idx.indkey[i] ik
        FROM
          generate_subscripts(idx.indkey, 1) i
      ) f
    JOIN
      pg_attribute T
        ON (T.attrelid, T.attnum) = (f.rel, f.ik)
  ) fld$
, (
    SELECT
      array_agg(replace(opcname::text, '_ops', '') ORDER BY f.i)
    FROM
      (
        SELECT
          clr.oid rel
        , i
        , idx.indclass[i] ik
        FROM
          generate_subscripts(idx.indclass, 1) i
      ) f
    JOIN
      pg_opclass T
        ON T.oid = f.ik
  ) opc$
  FROM
    pg_class clr
  JOIN
    pg_index idx
      ON idx.indrelid = clr.oid
  JOIN
    pg_class cli
      ON cli.oid = idx.indexrelid
  JOIN
    pg_namespace nsp
      ON nsp.oid = cli.relnamespace AND
      nsp.nspname = (TABLE sch)
  WHERE
    NOT idx.indisunique AND
    idx.indisready AND
    idx.indisvalid
  ORDER BY
    clr.relname, cli.relname
)
, fld AS (
  SELECT
    *
  , ARRAY(
      SELECT
        (att::pg_attribute).attname
      FROM
        unnest(fld$) att
    ) nmf$
  , ARRAY(
      SELECT
        (
          SELECT
            typname
          FROM
            pg_type
          WHERE
            oid = (att::pg_attribute).atttypid
        )
      FROM
        unnest(fld$) att
    ) tpf$
  FROM
    def
)
SELECT
  nmt
, nmi
, def
, nmf$
, tpf$
, opc$
FROM
  fld
WHERE
  'timestamp' = ANY(tpf$[1:array_length(tpf$, 1) - 1]) OR
  'timestamptz' = ANY(tpf$[1:array_length(tpf$, 1) - 1]) OR
  'timestamp' = ANY(opc$[1:array_length(opc$, 1) - 1]) OR
  'timestamptz' = ANY(opc$[1:array_length(opc$, 1) - 1])
ORDER BY
  1, 2;

рдпрд╣рд╛рдВ рд╣рдо рддреБрд░рдВрдд рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЗрдирдкреБрдЯ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рд╡рд░реНрдЧреЛрдВ рдиреЗ рдЙрдиреНрд╣реЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ - рдЪреВрдВрдХрд┐ рдХреБрдЫ рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдкреНрдЯ-рдлрд╝рдВрдХреНрд╢рди рдЬреИрд╕реЗ date_trunc рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рдлрд╝реАрд▓реНрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

nmt | nmi         | def              | nmf$  | tpf$             | opc$
----------------------------------------------------------------------------------
tbl | tbl_b_a_idx | CREATE INDEX ... | {b,a} | {timestamp,int4} | {timestamp,int4}

рдмреБрд░рд╛: рдмрд╣реБрдд рдХрдо (рдмреВрд▓рд┐рдпрди)


рдЙрд╕реА рд╕рд┐рдХреНрдХреЗ рдХрд╛ рдлреНрд▓рд┐рдк рдкрдХреНрд╖, рдпрд╣ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдмрди рдЬрд╛рддреА рд╣реИ рдЬрд╣рд╛рдВ рд╕реВрдЪрдХрд╛рдВрдХ рдмреВрд▓рд┐рдпрди-рдлрд╝реАрд▓реНрдб рд╣реИ , рдЬреЛ рдХреЗрд╡рд▓ 3 рдорд╛рди рд▓реЗ рд╕рдХрддрд╛ рд╣реИ NULL, FALSE, TRUEред рдмреЗрд╢рдХ, рдЗрд╕рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рд╕рдордЭ рдореЗрдВ рдЖрддреА рд╣реИ рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд▓рд╛рдЧреВ рдЫрдБрдЯрд╛рдИ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЗрдВ рдкреЗрдбрд╝ рдХреЗ рдкрджрд╛рдиреБрдХреНрд░рдо рдореЗрдВ рдиреЛрдб рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╛рдорд┐рдд рдХрд░рдХреЗ - рдЪрд╛рд╣реЗ рд╡рд╣ рдПрдХ рдлрд╝реЛрд▓реНрдбрд░ рд╣реЛ рдпрд╛ рдПрдХ рдкрддреНрддрд╛ ("рдлрд╝реЛрд▓реНрдбрд░ рдкрд╣рд▓реЗ")ред

CREATE TABLE tbl(
  id
    serial
      PRIMARY KEY
, leaf_pid
    integer
, leaf_type
    boolean
, public
    boolean
);
CREATE INDEX ON tbl(leaf_pid, leaf_type); --   
CREATE INDEX ON tbl(public, id); -- - 

рд▓реЗрдХрд┐рди, рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЕрдиреБрд░реЛрдз рдмреВрд▓рд┐рдпрди рдХреНрд╖реЗрддреНрд░ рдХреЗ рдХреБрдЫ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде рдЖрддреЗ рд╣реИрдВред рдФрд░ рдлрд┐рд░ рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдЗрд╕рдХреЗ рд╕рд╢рд░реНрдд рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ:

CREATE INDEX ON tbl(id) WHERE public;

рдЗрдВрдбреЗрдХреНрд╕ рдореЗрдВ рдмреВрд▓рд┐рдпрди рдЦреЛрдЬ рдХреНрд╡реЗрд░реА
WITH sch AS (
  SELECT
    'public'::text sch -- schema
)
, def AS (
  SELECT
    clr.relname nmt
  , cli.relname nmi
  , pg_get_indexdef(cli.oid) def
  , cli.oid clioid
  , clr
  , cli
  , idx
, (
    SELECT
      array_agg(T::text ORDER BY f.i)
    FROM
      (
        SELECT
          clr.oid rel
        , i
        , idx.indkey[i] ik
        FROM
          generate_subscripts(idx.indkey, 1) i
      ) f
    JOIN
      pg_attribute T
        ON (T.attrelid, T.attnum) = (f.rel, f.ik)
  ) fld$
, (
    SELECT
      array_agg(replace(opcname::text, '_ops', '') ORDER BY f.i)
    FROM
      (
        SELECT
          clr.oid rel
        , i
        , idx.indclass[i] ik
        FROM
          generate_subscripts(idx.indclass, 1) i
      ) f
    JOIN
      pg_opclass T
        ON T.oid = f.ik
  ) opc$
  FROM
    pg_class clr
  JOIN
    pg_index idx
      ON idx.indrelid = clr.oid
  JOIN
    pg_class cli
      ON cli.oid = idx.indexrelid
  JOIN
    pg_namespace nsp
      ON nsp.oid = cli.relnamespace AND
      nsp.nspname = (TABLE sch)
  WHERE
    NOT idx.indisunique AND
    idx.indisready AND
    idx.indisvalid
  ORDER BY
    clr.relname, cli.relname
)
, fld AS (
  SELECT
    *
  , ARRAY(
      SELECT
        (att::pg_attribute).attname
      FROM
        unnest(fld$) att
    ) nmf$
  , ARRAY(
      SELECT
        (
          SELECT
            typname
          FROM
            pg_type
          WHERE
            oid = (att::pg_attribute).atttypid
        )
      FROM
        unnest(fld$) att
    ) tpf$
  FROM
    def
)
SELECT
  nmt
, nmi
, def
, nmf$
, tpf$
, opc$
FROM
  fld
WHERE
  (
    'bool' = ANY(tpf$) OR
    'bool' = ANY(opc$)
  ) AND
  NOT(
    ARRAY(
      SELECT
        nmf$[i:i+1]::text
      FROM
        generate_series(1, array_length(nmf$, 1) - 1) i
    ) &&
    ARRAY[ --  -  
      '{leaf_pid,leaf_type}'
    ]
  )
ORDER BY
  1, 2;

nmt | nmi               | def              | nmf$        | tpf$        | opc$
------------------------------------------------------------------------------------
tbl | tbl_public_id_idx | CREATE INDEX ... | {public,id} | {bool,int4} | {bool,int4}

Btree рдореЗрдВ рдЖрддрд╛ рд╣реИ


рдПрдХ рдЕрд▓рдЧ рдмрд┐рдВрджреБ btree рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ "рд╕рд░рдгреА рдХреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдиреЗ" рдХрд╛ рдкреНрд░рдпрд╛рд╕ рд╣реИред рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдВрднрд╡ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рдСрдкрд░реЗрдЯрд░ рдЙрди рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ :
(<, >, = . .) , B-, , . ( ). , , .
рд▓реЗрдХрд┐рди рджрд┐рдХреНрдХрдд рдпрд╣ рд╣реИ рдХрд┐ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдкреНрд░рдпреЛрдЧ рд╡рд╣ рдЪрд╛рд╣рддрд╛ рд╣реИ рд╢рд╛рдорд┐рд▓ рдХрд┐рдП рдЬрд╛рдиреЗ рдФрд░ рдЪреМрд░рд╛рд╣реЗ рдХреЗ рдСрдкрд░реЗрдЯрд░реЛрдВ : <@, @>, &&ред рдмреЗрд╢рдХ, рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ - рдХреНрдпреЛрдВрдХрд┐ рдЙрдиреНрд╣реЗрдВ рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ ред рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рддрддреНрд╡ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдЗрд╕ рддрд░рд╣ рдХреЗ рдмреАрдЯреНрд░реА рдХреИрд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ arr[i]ред

рд╣рдо рдЗрд╕ рддрд░рд╣ рдХреА рдЦреЛрдЬ рдХрд░рдирд╛ рд╕реАрдЦрддреЗ рд╣реИрдВ:

CREATE TABLE tbl(
  id
    serial
      PRIMARY KEY
, pid
    integer
, list
    integer[]
);
CREATE INDEX ON tbl(pid);
CREATE INDEX ON tbl(list); -- - 

Btree рдореЗрдВ рдЕрд░реНрд░реЗ рд╕рд░реНрдЪ рдХреНрд╡реЗрд░реА
WITH sch AS (
  SELECT
    'public'::text sch -- schema
)
, def AS (
  SELECT
    clr.relname nmt
  , cli.relname nmi
  , pg_get_indexdef(cli.oid) def
  , cli.oid clioid
  , clr
  , cli
  , idx
, (
    SELECT
      array_agg(T::text ORDER BY f.i)
    FROM
      (
        SELECT
          clr.oid rel
        , i
        , idx.indkey[i] ik
        FROM
          generate_subscripts(idx.indkey, 1) i
      ) f
    JOIN
      pg_attribute T
        ON (T.attrelid, T.attnum) = (f.rel, f.ik)
  ) fld$
  FROM
    pg_class clr
  JOIN
    pg_index idx
      ON idx.indrelid = clr.oid
  JOIN
    pg_class cli
      ON cli.oid = idx.indexrelid
  JOIN
    pg_namespace nsp
      ON nsp.oid = cli.relnamespace AND
      nsp.nspname = (TABLE sch)
  WHERE
    NOT idx.indisunique AND
    idx.indisready AND
    idx.indisvalid AND
    cli.relam = (
      SELECT
        oid
      FROM
        pg_am
      WHERE
        amname = 'btree'
      LIMIT 1
    )
  ORDER BY
    clr.relname, cli.relname
)
, fld AS (
  SELECT
    *
  , ARRAY(
      SELECT
        (att::pg_attribute).attname
      FROM
        unnest(fld$) att
    ) nmf$
  , ARRAY(
      SELECT
        (
          SELECT
            typname
          FROM
            pg_type
          WHERE
            oid = (att::pg_attribute).atttypid
        )
      FROM
        unnest(fld$) att
    ) tpf$
  FROM
    def
)
SELECT
  nmt
, nmi
, nmf$
, tpf$
, def
FROM
  fld
WHERE
  tpf$ && ARRAY(
    SELECT
      typname
    FROM
      pg_type
    WHERE
      typname ~ '^_'
  )
ORDER BY
  1, 2;

nmt | nmi          | nmf$   | tpf$    | def
--------------------------------------------------------
tbl | tbl_list_idx | {list} | {_int4} | CREATE INDEX ...

рдкреВрд░реНрдг рд╕реВрдЪрдХрд╛рдВрдХ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ


рдкрд┐рдЫрд▓реА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд╕рдорд╕реНрдпрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреВрд░реНрдг рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕реВрдЪрдХрд╛рдВрдХ "рд▓рд┐рдЯ" рд╣реИред рдпрд╣реА рд╣реИ, рд░рд┐рдХреЙрд░реНрдб рдЬрд╣рд╛рдВ рдХреЙрд▓рдо рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ рдЕрдиреБрдХреНрд░рдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ NULL рд╣реИ ред рдЗрд╕ рддрд░рд╣ рдХреЗ рд░рд┐рдХреЙрд░реНрдб рдХрд╛ рдХреЛрдИ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд▓рд╛рдн рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХреЗ рд╕рд╛рде рдиреБрдХрд╕рд╛рди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред

рдЖрдорддреМрд░ рдкрд░ рд╡реЗ рддрдм рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ рдЬрдм рдЖрдк рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╡реИрдХрд▓реНрдкрд┐рдХ рдкреИрдбрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рдПрдлрдХреЗ рдлрд╝реАрд▓реНрдб рдпрд╛ рдореВрд▓реНрдп рд╕рдВрдмрдВрдз рдмрдирд╛рддреЗ рд╣реИрдВред рдлрд┐рд░ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рд░реЛрд▓ рдХрд░реЗрдВ рддрд╛рдХрд┐ рдПрдлрдХреЗ рдЬрд▓реНрджреА рд╕реЗ рдХрд╛рдо рдХрд░реЗ ... рдФрд░ рдпрд╣рд╛рдВ рд╡реЗ рд╣реИрдВред рдЬрд┐рддрдирд╛ рдХрдо рдмрд╛рд░ рдХрдиреЗрдХреНрд╢рди рднрд░рд╛ рдЬрд╛рдПрдЧрд╛, рдЙрддрдирд╛ рдЕрдзрд┐рдХ "рдХрдЪрд░рд╛" рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдЧрд┐рд░ рдЬрд╛рдПрдЧрд╛ред рд╣рдо рдЕрдиреБрдХрд░рдг рдХрд░реЗрдВрдЧреЗ:

CREATE TABLE tbl(
  id
    serial
      PRIMARY KEY
, fk
    integer
);
CREATE INDEX ON tbl(fk);

INSERT INTO tbl(fk)
SELECT
  CASE WHEN i % 10 = 0 THEN i END
FROM
  generate_series(1, 1000000) i;

рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рд╕рд╢рд░реНрдд рдПрдХ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдХрдо рднреА рд▓рдЧрддрд╛ рд╣реИ:

CREATE INDEX ON tbl(fk) WHERE (fk) IS NOT NULL;

_tmp=# \di+ tbl*
                               List of relations
 Schema |      Name      | Type  |  Owner   |  Table   |  Size   | Description
--------+----------------+-------+----------+----------+---------+-------------
 public | tbl_fk_idx     | index | postgres | tbl      | 36 MB   |
 public | tbl_fk_idx1    | index | postgres | tbl      | 2208 kB |
 public | tbl_pkey       | index | postgres | tbl      | 21 MB   |

рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд┐рддрд░рдг рдХреЛ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдЕрд░реНрдерд╛рддреН , рдЖрдЦрд┐рд░рдХрд╛рд░ , рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреА рд╕рднреА рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЛ рдкрдврд╝реЗрдВ рдФрд░ рдШрдЯрдирд╛ рдХреА WHERE- рд╢рд░реНрддреЛрдВ (рд╣рдо рдЗрд╕реЗ dblink рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдРрд╕рд╛ рдХрд░реЗрдВрдЧреЗ ) рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕реБрдкрд░рдордкреЛрдЬ рдХрд░реЗрдВ , рдЬрд┐рд╕рдореЗрдВ рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╕рдордп рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ ред

рдЕрдиреБрдХреНрд░рдорд┐рдд рдореЗрдВ NULL рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЦреЛрдЬ рдХреНрд╡реЗрд░реА
WITH sch AS (
  SELECT
    'public'::text sch -- schema
)
, def AS (
  SELECT
    clr.relname nmt
  , cli.relname nmi
  , pg_get_indexdef(cli.oid) def
  , cli.oid clioid
  , clr
  , cli
  FROM
    pg_class clr
  JOIN
    pg_index idx
      ON idx.indrelid = clr.oid
  JOIN
    pg_class cli
      ON cli.oid = idx.indexrelid
  JOIN
    pg_namespace nsp
      ON nsp.oid = cli.relnamespace AND
      nsp.nspname = (TABLE sch)
  WHERE
    NOT idx.indisprimary AND
    idx.indisready AND
    idx.indisvalid AND
    NOT EXISTS(
      SELECT
        NULL
      FROM
        pg_constraint
      WHERE
        conindid = cli.oid
      LIMIT 1
    ) AND
    pg_relation_size(cli.oid) > 1 << 20 --  1MB   
  ORDER BY
    clr.relname, cli.relname
)
, fld AS (
  SELECT
    *
  , regexp_replace(
      CASE
        WHEN def ~ ' USING btree ' THEN
          regexp_replace(def, E'.* USING btree (.*?)($| WHERE .*)', E'\\1')
      END
    , E' ([a-z]*_pattern_ops|(ASC|DESC)|NULLS\\s?(?:FIRST|LAST))'
    , ''
    , 'ig'
    ) fld
  , CASE
      WHEN def ~ ' WHERE ' THEN regexp_replace(def, E'.* WHERE ', '')
    END wh
  FROM
    def
)
, q AS (
  SELECT
    nmt
  , $q$-- $q$ || quote_ident(nmt) || $q$
      SET search_path = $q$ || quote_ident((TABLE sch)) || $q$, public;
      SELECT
        ARRAY[
          count(*)
        $q$ || string_agg(
          ', coalesce(sum((' || coalesce(wh, 'TRUE') || ')::integer), 0)' || E'\n' ||
          ', coalesce(sum(((' || coalesce(wh, 'TRUE') || ') AND (' || fld || ' IS NULL))::integer), 0)' || E'\n'
        , '' ORDER BY nmi) || $q$
        ]
      FROM
        $q$ || quote_ident((TABLE sch)) || $q$.$q$ || quote_ident(nmt) || $q$
    $q$ q
  , array_agg(clioid ORDER BY nmi) oid$
  , array_agg(nmi ORDER BY nmi) idx$
  , array_agg(fld ORDER BY nmi) fld$
  , array_agg(wh ORDER BY nmi) wh$
  FROM
    fld
  WHERE
    fld IS NOT NULL
  GROUP BY
    1
  ORDER BY
    1
)
, res AS (
  SELECT
    *
  , (
      SELECT
        qty
      FROM
        dblink(
          'dbname=' || current_database() || ' port=' || current_setting('port')
        , q
        ) T(qty bigint[])
    ) qty
  FROM
    q
)
, iter AS (
  SELECT
    *
  , generate_subscripts(idx$, 1) i
  FROM
    res
)
, stat AS (
  SELECT
    nmt table_name
  , idx$[i] index_name
  , pg_relation_size(oid$[i]) index_size
  , pg_size_pretty(pg_relation_size(oid$[i])) index_size_humanize
  , regexp_replace(fld$[i], E'^\\((.*)\\)$', E'\\1') index_fields
  , regexp_replace(wh$[i], E'^\\((.*)\\)$', E'\\1') index_cond
  , qty[1] table_rec_count
  , qty[i * 2] index_rec_count
  , qty[i * 2 + 1] index_rec_count_null
  FROM
    iter
)
SELECT
  *
, CASE
    WHEN table_rec_count > 0
      THEN index_rec_count::double precision / table_rec_count::double precision * 100
    ELSE 0
  END::numeric(32,2) index_cover_prc
, CASE
    WHEN index_rec_count > 0
      THEN index_rec_count_null::double precision / index_rec_count::double precision * 100
    ELSE 0
  END::numeric(32,2) index_null_prc
FROM
  stat
WHERE
  index_rec_count_null * 4 > index_rec_count --   NULL-
ORDER BY
  1, 2;

-[ RECORD 1 ]--------+--------------
table_name           | tbl
index_name           | tbl_fk_idx
index_size           | 37838848
index_size_humanize  | 36 MB
index_fields         | fk
index_cond           |
table_rec_count      | 1000000
index_rec_count      | 1000000
index_rec_count_null | 900000
index_cover_prc      | 100.00 -- 100%    
index_null_prc       | 90.00  --   90% NULL-""

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдХреБрдЫ рдкреНрд░рд╢реНрди рдЖрдкрдХреА рдорджрдж рдХрд░реЗрдВрдЧреЗред

All Articles