рд╣рдо рдкрд╣рд▓реЗ рд╣реА PostgreSQL
рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдЗрдВрдЬрди рдФрд░ рдПрдХреНрд╕реЗрд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдЗрдВрдЯрд░рдлреЗрд╕ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛ рдЪреБрдХреЗ рд╣реИрдВ рдФрд░
рд╣реИрд╢ рдЗрдВрдбреЗрдХреНрд╕ ,
рдмреА- рдЯреНрд░реАрдЬрд╝ , рд╕рд╛рде рд╣реА рд╕рд╛рде
рдЬреАрдПрд╕рдЯреА рдФрд░
рдПрд╕рдкреА-рдЬреАрдПрд╕рдЯреА рдЗрдВрдбреЗрдХреНрд╕ рдкрд░
рдЪрд░реНрдЪрд╛ рдХреА рд╣реИ ред рдФрд░ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ GIN рдЗрдВрдбреЗрдХреНрд╕ рдХреА рд╕реБрд╡рд┐рдзрд╛ рд╣реЛрдЧреАред
рдЬрд┐рди
"рдЬрд┐рди? .. рдЬрд┐рди рд╣реИ, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ, рдРрд╕реА рдЕрдореЗрд░рд┐рдХреА рд╢рд░рд╛рдм? ..?"
"рдореИрдВ рдПрдХ рдбреНрд░рд┐рдВрдХ рдирд╣реАрдВ рд╣реВрдБ, рдУрд╣, рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рд▓рдбрд╝рдХрд╛!" рдлрд┐рд░ рд╕реЗ рд╡рд╣ рдмреВрдврд╝рд╛ рдЖрджрдореА рднрдбрд╝рдХ рдЧрдпрд╛, рдлрд┐рд░ рд╕реЗ рдЙрд╕рдиреЗ рдЦреБрдж рдХреЛ рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛ рдФрд░ рдлрд┐рд░ рд╕реЗ рдЦреБрдж рдХреЛ рд╕рдВрднрд╛рд▓ рд▓рд┐рдпрд╛ред "рдореИрдВ рдПрдХ рдкреЗрдп рдирд╣реАрдВ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдПрдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдФрд░ рдЕрднрджреНрд░ рдЖрддреНрдорд╛ рд╣реВрдВ, рдФрд░ рджреБрдирд┐рдпрд╛ рдореЗрдВ рдРрд╕рд╛ рдХреЛрдИ рдЬрд╛рджреВ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдореИрдВ рдирд╣реАрдВ рдХрд░ рдкрд╛рдКрдВрдЧрд╛ред"- рд▓рдЬрд╝рд╛рд░ рд▓рд╛рдЧрд┐рди, "рдУрд▓реНрдб рдЦреЛрдЯреИрдмрдЪред"
рдЬрд┐рди рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдЙрд▓реНрдЯреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд▓рд┐рдП рдЦрдбрд╝рд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдПрдХ рдЬрд┐рдиреНрди рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдПрдХ рдкреЗрдп рдХреЗ рд░реВрдк рдореЗрдВред-
READMEрд╕рд╛рдорд╛рдиреНрдп рдЕрд╡рдзрд╛рд░рдгрд╛
GIN рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░реВрдк рд╕реЗ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдФрдВрдзрд╛ рд╕реВрдЪрдХрд╛рдВрдХ рд╣реИред рдпрд╣ рдПрдХ рддрдерд╛рдХрдерд┐рдд
рдЙрд▓реНрдЯрд╛ рд╕реВрдЪрдХрд╛рдВрдХ рд╣реИ ред рдпрд╣ рдЙрди рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рдирдХреЗ рдореВрд▓реНрдп рдкрд░рдорд╛рдгреБ рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рддрддреНрд╡реЛрдВ рд╕реЗ рдорд┐рд▓рдХрд░ рд╣реЛрддреЗ рд╣реИрдВред рд╣рдо рдЗрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдпреМрдЧрд┐рдХ рдХрд╣реЗрдВрдЧреЗред рдФрд░ рдпреЗ рд╡реЗ рдореВрд▓реНрдп рдирд╣реАрдВ рд╣реИрдВ рдЬреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рд╡реНрдпрдХреНрддрд┐рдЧрдд рддрддреНрд╡; рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдЙрди рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдпрд╣ рд╣реЛрддрд╛ рд╣реИред
рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рд╛рджреГрд╢реНрдп рдПрдХ рдкреБрд╕реНрддрдХ рдХреЗ рдЕрдВрдд рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рд╣реИ, рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рд╢рдмреНрдж рдХреЗ рд▓рд┐рдП, рдЙрди рдкреГрд╖реНрдареЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдпрд╣ рд╢рдмреНрдж рд╣реЛрддрд╛ рд╣реИред рдкрд╣реБрдВрдЪ рд╡рд┐рдзрд┐ рдХреЛ рдХрд┐рд╕реА рдкреБрд╕реНрддрдХ рдореЗрдВ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреА рддрд░рд╣ рдЕрдиреБрдХреНрд░рдорд┐рдд рддрддреНрд╡реЛрдВ рдХреА рддреЗрдЬреА рд╕реЗ рдЦреЛрдЬ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП, рдЗрди рддрддреНрд╡реЛрдВ рдХреЛ рдПрдХ рдкрд░рд┐рдЪрд┐рдд
рдмреА-рдкреЗрдбрд╝ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдПрдХ рдЕрд▓рдЧ, рд╕рд░рд▓, рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛)ред рддрд╛рд▓рд┐рдХрд╛ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╕реЗрдЯ рдЬрд┐рд╕рдореЗрдВ рддрддреНрд╡ рдХреЗ рд╕рд╛рде рдпреМрдЧрд┐рдХ рдореВрд▓реНрдп рд╣реЛрддреЗ рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИред рдбреЗрдЯрд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддрд┐ (TIDs рдХрд╛ рдХреНрд░рдо рдХреНрд░рдо рдмрд╣реБрдд рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ) рдХреЗ рд▓рд┐рдП рдХреНрд░рдорд┐рдХ рдорд╣рддреНрд╡рд╣реАрди рд╣реИ, рд▓реЗрдХрд┐рди рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред
рддрддреНрд╡реЛрдВ рдХреЛ GIN рдЗрдВрдбреЗрдХреНрд╕ рд╕реЗ рдХрднреА рдбрд┐рд▓реАрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рддрддреНрд╡реЛрдВ рд╕реЗ рдпреБрдХреНрдд рдорд╛рди рдЧрд╛рдпрдм рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрддреНрдкрдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬрд┐рди рддрддреНрд╡реЛрдВ рд╕реЗ рдЙрдирдХреА рд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИ, рдЙрдирдХрд╛ рд╕реЗрдЯ рдЕрдзрд┐рдХ рдпрд╛ рдХрдо рд╕реНрдерд┐рд░ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рд╕рдорд╛рдзрд╛рди рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдХрдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕рдорд╡рд░реНрддреА рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд░реВрдк рд╕реЗ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИред
рдпрджрд┐ TID рдХреА рд╕реВрдЪреА рдмрд╣реБрдд рдЫреЛрдЯреА рд╣реИ, рддреЛ рдпрд╣ рддрддреНрд╡ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╣реА рдкреГрд╖реНрда рдореЗрдВ рдлрд┐рдЯ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдФрд░ рдЗрд╕реЗ "рдкреЛрд╕реНрдЯрд┐рдВрдЧ рд╕реВрдЪреА" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╕реВрдЪреА рдмрдбрд╝реА рд╣реИ, рддреЛ рдПрдХ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ - рдпрд╣ рдлрд┐рд░ рд╕реЗ рдмреА-рдЯреНрд░реА рд╣реИред рдРрд╕рд╛ рдкреЗрдбрд╝ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдбреЗрдЯрд╛ рдкреГрд╖реНрдареЛрдВ рдкрд░ рд╕реНрдерд┐рдд рд╣реИ (рдФрд░ рдЗрд╕реЗ "рдкреЛрд╕реНрдЯрд┐рдВрдЧ рдЯреНрд░реА" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ)ред
рддреЛ, GIN рдЗрдВрдбреЗрдХреНрд╕ рдореЗрдВ B- рдЯреНрд░реА рдСрдлрд╝ рдПрд▓рд┐рдореЗрдВрдЯреНрд╕ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ B-рдЯреНрд░реА рдпрд╛ TID рдХреА рдлреНрд▓реИрдЯ рд▓рд┐рд╕реНрдЯ рдЙрд╕ B- рдЯреНрд░реА рдХреА рд▓реАрдл рдкрдВрдХреНрддрд┐рдпреЛрдВ рд╕реЗ рдЬреБрдбрд╝реА рд╣реЛрддреА рд╣реИред
рдкрд╣рд▓реЗ рдЪрд░реНрдЪрд╛ рдХрд┐рдП рдЧрдП GiST рдФрд░ SP-GiST рдЗрдВрдбреЗрдХреНрд╕ рдХреА рддрд░рд╣, GIN рдХрдВрдкрд╛рдЙрдВрдб рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдбреЗрд╡рд▓рдкрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ
GIN рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреНрд╖реЗрддреНрд░ рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ рдХреЛ рдЧрддрд┐ рджреЗ рд░рд╣рд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдЪрд░реНрдЪрд╛ рдореЗрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдЪрд┐рдд рд╣реИред
GiST рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд▓реЗрдЦ рдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдкрд░рд┐рдЪрдп рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЪрд▓реЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рдмрд┐рдирд╛ рд╕реАрдзреЗ рдмрд┐рдВрджреБ рдкрд░ рдкрд╣реБрдВрдЪреЗрдВред рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпреМрдЧрд┐рдХ рдореВрд▓реНрдп
рджрд╕реНрддрд╛рд╡реЗрдЬ рд╣реИрдВ , рдФрд░ рдЗрди рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдХреЗ рддрддреНрд╡
lexemes рд╣реИрдВ ред
рдЖрдЗрдП GiST- рд╕рдВрдмрдВрдзрд┐рдд рд▓реЗрдЦ рд╕реЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
postgres=# create table ts(doc text, doc_tsv tsvector); postgres=# insert into ts(doc) values ('Can a sheet slitter slit sheets?'), ('How many sheets could a sheet slitter slit?'), ('I slit a sheet, a sheet I slit.'), ('Upon a slitted sheet I sit.'), ('Whoever slit the sheets is a good sheet slitter.'), ('I am a sheet slitter.'), ('I slit sheets.'), ('I am the sleekest sheet slitter that ever slit sheets.'), ('She slits the sheet she sits on.'); postgres=# update ts set doc_tsv = to_tsvector(doc); postgres=# create index on ts using gin(doc_tsv);
рдЗрд╕ рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдВрд░рдЪрдирд╛ рдЪрд┐рддреНрд░ рдореЗрдВ рджрд┐рдЦрд╛рдИ рдЧрдИ рд╣реИ:

рдкрд┐рдЫрд▓реЗ рд╕рднреА рдЖрдВрдХрдбрд╝реЛрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд, рддрд╛рд▓рд┐рдХрд╛ рдкрдВрдХреНрддрд┐рдпреЛрдВ (TID) рдХреЗ рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рддреАрд░ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдЕрдВрдзреЗрд░реЗ рдкреГрд╖реНрдарднреВрдорд┐ (рдкреГрд╖реНрда рдкрд░ рдкреГрд╖реНрда рд╕рдВрдЦреНрдпрд╛ рдФрд░ рд╕реНрдерд┐рддрд┐) рдкрд░ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
postgres=# select ctid, left(doc,20), doc_tsv from ts;
ctid | left | doc_tsv -------+----------------------+--------------------------------------------------------- (0,1) | Can a sheet slitter | 'sheet':3,6 'slit':5 'slitter':4 (0,2) | How many sheets coul | 'could':4 'mani':2 'sheet':3,6 'slit':8 'slitter':7 (0,3) | I slit a sheet, a sh | 'sheet':4,6 'slit':2,8 (1,1) | Upon a slitted sheet | 'sheet':4 'sit':6 'slit':3 'upon':1 (1,2) | Whoever slit the she | 'good':7 'sheet':4,8 'slit':2 'slitter':9 'whoever':1 (1,3) | I am a sheet slitter | 'sheet':4 'slitter':5 (2,1) | I slit sheets. | 'sheet':3 'slit':2 (2,2) | I am the sleekest sh | 'ever':8 'sheet':5,10 'sleekest':4 'slit':9 'slitter':6 (2,3) | She slits the sheet | 'sheet':4 'sit':6 'slit':2 (9 rows)
рдЗрд╕ рд╕рдЯреНрдЯрд╛ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЯреАрдЖрдИрдбреА тАЛтАЛрдХреА рд╕реВрдЪреА рд╕рднреА рд▓реЗрдХреНрд╕рдореЗрд╕ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдорд┐рдд рдкреГрд╖реНрдареЛрдВ рдореЗрдВ рдлрд┐рдЯ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди "рд╢реАрдЯ", "рд╕реНрд▓рд┐рдЯ" рдФрд░ "рд╕реНрд▓рд┐рдЯрд░"ред рдпреЗ рд▓реЗрдХреНрд╕реЗрдо рдХрдИ рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдореЗрдВ рд╣реБрдП, рдФрд░ рдЙрдирдХреЗ рд▓рд┐рдП TID рдХреА рд╕реВрдЪреА рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдмреА-рдкреЗрдбрд╝реЛрдВ рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред
рд╡реИрд╕реЗ, рд╣рдо рдХреИрд╕реЗ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рддрдиреЗ рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдореЗрдВ рдПрдХ рд▓реЗрдХреНрд╕реЗрдо рд╣реИ? рдПрдХ рдЫреЛрдЯреА рд╕реА рдореЗрдЬ рдХреЗ рд▓рд┐рдП, рдПрдХ "рдкреНрд░рддреНрдпрдХреНрд╖" рддрдХрдиреАрдХ, рдЬреЛ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдИ рдЧрдИ рд╣реИ, рдХрд╛рдо рдХрд░реЗрдЧреА, рд▓реЗрдХрд┐рди рд╣рдо рдЖрдЧреЗ рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рдмрдбрд╝реЗ рд▓реЛрдЧреЛрдВ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИред
postgres=# select (unnest(doc_tsv)).lexeme, count(*) from ts group by 1 order by 2 desc;
lexeme | count ----------+------- sheet | 9 slit | 8 slitter | 5 sit | 2 upon | 1 mani | 1 whoever | 1 sleekest | 1 good | 1 could | 1 ever | 1 (11 rows)
рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдХ рдирд┐рдпрдорд┐рдд рдмреА-рдЯреНрд░реА рдХреЗ рд╡рд┐рдкрд░реАрдд, GIN рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рдкреГрд╖реНрда рдПрдХ рджреНрд╡рд┐рджрд┐рд╢ рдХреА рдмрдЬрд╛рдп рдПрдХ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рд╕реВрдЪреА рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реЛрддреЗ рд╣реИрдВред рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рдкреЗрдбрд╝ рдХрд╛ рдирд┐рд╢рд╛рди рдХреЗрд╡рд▓ рдПрдХ рд╣реА рддрд░рд╣ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдПрдХ рдХреНрд╡реЗрд░реА рдХрд╛ рдЙрджрд╛рд╣рд░рдг
рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд╡реЗрд░реА рдХреИрд╕реЗ рдХреА рдЬрд╛рдПрдЧреА?
postgres=# explain(costs off) select doc from ts where doc_tsv @@ to_tsquery('many & slitter');
QUERY PLAN --------------------------------------------------------------------- Bitmap Heap Scan on ts Recheck Cond: (doc_tsv @@ to_tsquery('many & slitter'::text)) -> Bitmap Index Scan on ts_doc_tsv_idx Index Cond: (doc_tsv @@ to_tsquery('many & slitter'::text)) (4 rows)
рд╡реНрдпрдХреНрддрд┐рдЧрдд lexemes (рдЦреЛрдЬ рдХреБрдВрдЬреА) рдкрд╣рд▓реЗ рдХреНрд╡реЗрд░реА рд╕реЗ рдирд┐рдХрд╛рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ: "рдордгрд┐" рдФрд░ "рд╕реНрд▓реАрдЯрд░"ред рдпрд╣ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдПрдкреАрдЖрдИ рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдСрдкрд░реЗрдЯрд░ рд╡рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдФрд░ рд░рдгрдиреАрддрд┐ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддрд╛ рд╣реИ:
postgres=# select amop.amopopr::regoperator, amop.amopstrategy from pg_opclass opc, pg_opfamily opf, pg_am am, pg_amop amop where opc.opcname = 'tsvector_ops' and opf.oid = opc.opcfamily and am.oid = opf.opfmethod and amop.amopfamily = opc.opcfamily and am.amname = 'gin' and amop.amoplefttype = opc.opcintype;
amopopr | amopstrategy -----------------------+-------------- @@(tsvector,tsquery) | 1 matching search query @@@(tsvector,tsquery) | 2 synonym for @@ (for backward compatibility) (2 rows)
рд▓реЗрдХреНрд╕рдореЗрд╕ рдХреЗ рдмреА-рдЯреНрд░реА рдореЗрдВ, рд╣рдо рдЕрдЧрд▓реЗ рджреЛрдиреЛрдВ рдХреБрдВрдЬреА рдкрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЯреАрдЖрдИрдбреА тАЛтАЛрдХреА рддреИрдпрд╛рд░ рд╕реВрдЪреА рд╕реЗ рдЧреБрдЬрд░рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ:
"рдордгрд┐" рдХреЗ рд▓рд┐рдП - (0,2)ред
"рд╕реНрд▓реАрдЯрд░" рдХреЗ рд▓рд┐рдП - (0,1), (0,2), (1,2), (1,3), (2,2)ред

рдЕрдВрдд рдореЗрдВ, рдкрд╛рдпрд╛ рдЧрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ TID рдХреЗ рд▓рд┐рдП, рдПрдХ API рд╕рдВрдЧрддрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдХреМрди рд╕реА рдкрдВрдХреНрддрд┐рдпрд╛рдБ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИрдВред рдЪреВрдБрдХрд┐ рд╣рдорд╛рд░реА рдХреНрд╡реЗрд░реА рдореЗрдВ рд▓реЗрдХреНрд╕рдо рдмреВрд▓рд┐рдпрди рджреНрд╡рд╛рд░рд╛ рд╢рд╛рдорд┐рд▓ рдХрд┐рдП рдЧрдП рд╣реИрдВ "рдФрд░", рд▓реМрдЯреА рдПрдХрдорд╛рддреНрд░ рдкрдВрдХреНрддрд┐ рд╣реИ (0,2):
| | | consistency | | | function TID | mani | slitter | slit & slitter -------+------+---------+---------------- (0,1) | f | T | f (0,2) | T | T | T (1,2) | f | T | f (1,3) | f | T | f (2,2) | f | T | f
рдФрд░ рдкрд░рд┐рдгрд╛рдо рд╣реИ:
postgres=# select doc from ts where doc_tsv @@ to_tsquery('many & slitter');
doc --------------------------------------------- How many sheets could a sheet slitter slit? (1 row)
рдпрджрд┐ рд╣рдо рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рддреБрд▓рдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА GiST рдХреЗ рд▓рд┐рдП рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ, рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП GIN рдХрд╛ рд▓рд╛рдн рд╕реНрдкрд╖реНрдЯ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЖрдВрдЦ рд╕реЗ рдорд┐рд▓рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЗрд╕рдореЗрдВ рдФрд░ рднреА рдмрд╣реБрдд рдХреБрдЫ рд╣реИред
рдПрдХ рдзреАрдореА рдЕрджреНрдпрддрди рдХреА рд╕рдорд╕реНрдпрд╛
рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ GIN рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдпрд╛ рдЕрджреНрдпрддрди рдмрд╣реБрдд рдзреАрдорд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдЖрдорддреМрд░ рдкрд░ рдЕрдиреБрдХреНрд░рдорд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рд▓реЗрдХреНрд╕реЗрдо рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЬрдм рдХреЗрд╡рд▓ рдПрдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрд╛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЗрдВрдбреЗрдХреНрд╕ рдЯреНрд░реА рдХреЛ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рджреВрд╕рд░реА рдУрд░, рдпрджрд┐ рдХрдИ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рдПрдХ рд╕рд╛рде рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЙрдирдХреЗ рдХреБрдЫ рд▓реЗрдХреНрд╕реЗрдо рд╕рдорд╛рди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдПрдХ-рдПрдХ рдХрд░рдХреЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╕рдордп рдХрд╛рдо рдХреА рдХреБрд▓ рдорд╛рддреНрд░рд╛ рдЫреЛрдЯреА рд╣реЛрдЧреАред
GIN рдЗрдВрдбреЗрдХреНрд╕ рдореЗрдВ "рдлрд╛рд╕реНрдЯрдЕрдкрдбреЗрдЯ" рд╕реНрдЯреЛрд░реЗрдЬ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдЗрдВрдбреЗрдХреНрд╕ рдирд┐рд░реНрдорд╛рдг рдХреЗ рджреМрд░рд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдмрд╛рдж рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
postgres=# create index on ts using gin(doc_tsv) with (fastupdate = true);
рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдЪрд╛рд▓реВ рд╣реЛрдиреЗ рдХреЗ рд╕рд╛рде, рдЕрдкрдбреЗрдЯ рдПрдХ рдЕрд▓рдЧ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рд╕реВрдЪреА (рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЬреБрдбрд╝реЗ рдкреГрд╖реНрдареЛрдВ рдкрд░) рдореЗрдВ рдЬрдорд╛ рд╣реЛ рдЬрд╛рдПрдВрдЧреЗред рдЬрдм рдпрд╣ рд╕реВрдЪреА рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рдпрд╛ рд╡реИрдХреНрдпреВрдорд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдмрдбрд╝реА рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рд╕рднреА рд╕рдВрдЪрд┐рдд рдЕрдкрдбреЗрдЯ рддреБрд░рдВрдд рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред "рдмрдбрд╝реА рдкрд░реНрдпрд╛рдкреНрдд" рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреМрди рд╕реА рд╕реВрдЪреА "gin_pending_list_limit" рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ рдпрд╛ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд╕рдорд╛рди-рдирд╛рдо рд╕рдВрдЧреНрд░рд╣рдг рдкреИрд░рд╛рдореАрдЯрд░ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред
рд▓реЗрдХрд┐рди рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдХрдорд┐рдпрд╛рдВ рд╣реИрдВ: рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЦреЛрдЬ рдХреЛ рдзреАрдорд╛ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЪреВрдВрдХрд┐ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рд╕реВрдЪреА рдХреЛ рдкреЗрдбрд╝ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рджреЗрдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП), рдФрд░ рджреВрд╕рд░рд╛, рдПрдХ рдЕрдЧрд▓рд╛ рдЕрджреНрдпрддрди рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд░реВрдк рд╕реЗ рдЬреНрдпрд╛рджрд╛ рд╕рдордп рд▓реЗ рд╕рдХрддрд╛ рд╣реИ рдЕрдЧрд░ рдЕрдирдСрд░реНрдбрд░реНрдб рдХреА рдЧрдИ рд╕реВрдЪреА рдХреЛ рдУрд╡рд░рдлреНрд▓реЛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛред
рдЖрдВрд╢рд┐рдХ рдореИрдЪ рдХреА рдЦреЛрдЬ
рд╣рдо рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ рдореЗрдВ рдЖрдВрд╢рд┐рдХ рдорд┐рд▓рд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╢реНрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
gin=# select doc from ts where doc_tsv @@ to_tsquery('slit:*');
doc -------------------------------------------------------- Can a sheet slitter slit sheets? How many sheets could a sheet slitter slit? I slit a sheet, a sheet I slit. Upon a slitted sheet I sit. Whoever slit the sheets is a good sheet slitter. I am a sheet slitter. I slit sheets. I am the sleekest sheet slitter that ever slit sheets. She slits the sheet she sits on. (9 rows)
рдЗрд╕ рдХреНрд╡реЗрд░реА рдореЗрдВ рдРрд╕реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдорд┐рд▓реЗрдВрдЧреЗ, рдЬрд┐рдирдореЗрдВ "рд╕реНрд▓рд┐рдЯ" рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд▓реЗрдХреНрд╕реЗрдо рд╣реИрдВред рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдРрд╕реЗ рд▓реЗрдХреНрд╕реЗрдо "рд╕реНрд▓рд┐рдЯ" рдФрд░ "рд╕реНрд▓рд┐рдЯрд░" рд╣реИрдВред
рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреЗ рдмрд┐рдирд╛ рднреА, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдХреНрд╡реЗрд░реА рдХрд╛рдо рдХрд░реЗрдЧреА, рд▓реЗрдХрд┐рди GIN рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЦреЛрдЬ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:
postgres=# explain (costs off) select doc from ts where doc_tsv @@ to_tsquery('slit:*');
QUERY PLAN ------------------------------------------------------------- Bitmap Heap Scan on ts Recheck Cond: (doc_tsv @@ to_tsquery('slit:*'::text)) -> Bitmap Index Scan on ts_doc_tsv_idx Index Cond: (doc_tsv @@ to_tsquery('slit:*'::text)) (4 rows)
рдпрд╣рд╛рдБ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЙрдкрд╕рд░реНрдЧ рд╡рд╛рд▓реЗ рд╕рднреА lexemes рдХреЛ рдкреЗрдбрд╝ рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдмреВрд▓рд┐рдпрди "рдпрд╛" рджреНрд╡рд╛рд░рд╛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред
рдмрд╛рд░-рдмрд╛рд░ рдФрд░ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд lexemes
рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд▓рд╛рдЗрд╡ рдбреЗрдЯрд╛ рдкрд░ рдЗрдВрдбреЗрдХреНрд╕рд┐рдВрдЧ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЪрд▓реЛ "pgsql-hackers" рдИрдореЗрд▓ рдХрд╛ рд╕рдВрдЧреНрд░рд╣ рд▓реЗрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдкрд╣рд▓реЗ рд╣реА GiST рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддреЗ рд╕рдордп рдХрд░ рдЪреБрдХреЗ рд╣реИрдВред
рд╕рдВрдЧреНрд░рд╣ рдХреЗ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рднреЗрдЬрдиреЗ рдХреА рддрд╛рд░реАрдЦ, рд╡рд┐рд╖рдп, рд▓реЗрдЦрдХ рдФрд░ рдкрд╛рда рдХреЗ рд╕рд╛рде 356125 рд╕рдВрджреЗрд╢ рд╣реИрдВред
fts=# alter table mail_messages add column tsv tsvector; fts=# update mail_messages set tsv = to_tsvector(body_plain);
NOTICE: word is too long to be indexed DETAIL: Words longer than 2047 characters are ignored. ... UPDATE 356125
fts=# create index on mail_messages using gin(tsv);
рдЖрдЗрдП рдПрдХ рд▓реЗрдХреНрд╕реЗрдо рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдЬреЛ рдХрдИ рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред "рдЕрдирд╛рд╡рд╢реНрдпрдХ" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдХреНрд╡реЗрд░реА рдЗрддрдиреЗ рдмрдбрд╝реЗ рдбреЗрдЯрд╛ рдЖрдХрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧреА, рдФрд░ рд╕рд╣реА рддрдХрдиреАрдХ "ts_stat" рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдЬреЛ рд▓реЗрдХреНрд╕реЗрдо рдкрд░ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╡реЗ рд╣реБрдП рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛, рдФрд░ рдШрдЯрдирд╛рдУрдВ рдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛ред
fts=# select word, ndoc from ts_stat('select tsv from mail_messages') order by ndoc desc limit 3;
word | ndoc -------+-------- re | 322141 wrote | 231174 use | 176917 (3 rows)
рдЪрд▓реЛ "рд▓рд┐рдЦрд╛" рдЪреБрдиреЗрдВред
рдФрд░ рд╣рдо рдХреБрдЫ рд╢рдмреНрдж рд▓реЗрдВрдЧреЗ рдЬреЛ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рдИрдореЗрд▓ рдХреЗ рд▓рд┐рдП рдЕрдиреВрдареЗ рд╣реИрдВ, рдХрд╣рддреЗ рд╣реИрдВ, "рдЯреИрдЯреВ":
fts=# select word, ndoc from ts_stat('select tsv from mail_messages') where word = 'tattoo';
word | ndoc --------+------ tattoo | 2 (1 row)
рдХреНрдпрд╛ рдРрд╕реЗ рдХреЛрдИ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВ рдЬрд╣рд╛рдБ рдпреЗ рджреЛрдиреЛрдВ рд▓реЗрдХреНрдореЗ рдЖрддреЗ рд╣реИрдВ? рдРрд╕рд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рд╡рд╣рд╛рдБ рд╣реИрдВ:
fts=# select count(*) from mail_messages where tsv @@ to_tsquery('wrote & tattoo');
count ------- 1 (1 row)
рдПрдХ рдкреНрд░рд╢реНрди рдЙрдарддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдХреНрд╡реЗрд░реА рдХреЛ рдХреИрд╕реЗ рдХрд░реЗрдВред рдпрджрд┐ рд╣рдо рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЯреАрдЖрдИрдбреА тАЛтАЛрдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╣реИ, рддреЛ рдЦреЛрдЬ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрдХреНрд╖рдо рд╣реЛрдЧреА: рд╣рдореЗрдВ 200 рд╣рдЬрд╛рд░ рд╕реЗ рдЕрдзрд┐рдХ рдореВрд▓реНрдпреЛрдВ рд╕реЗ рдЧреБрдЬрд░рдирд╛ рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рд╢реЗрд╖ рд╣реЛрдЧрд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдпреЛрдЬрдирд╛рдХрд╛рд░ рдЖрдВрдХрдбрд╝реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╕рдордЭрддрд╛ рд╣реИ рдХрд┐ "рд▓рд┐рдЦрд╛" рд▓реЗрдХреНрд╕реЗрдо рдЕрдХреНрд╕рд░ рд╣реЛрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ "рдЯрдЯреВ" рдЕрдХреНрд╕рд░ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЕрд╕реАрдо рд▓реЗрдХреНрд╕реЗрдо рдХреА рдЦреЛрдЬ рдХреА рдЬрд╛рддреА рд╣реИ, рдФрд░ рдлрд┐рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдЧрдП рджреЛ рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдХреЛ "рд▓рд┐рдЦрд┐рдд" рд▓реЗрдХреНрд╕реЗрдо рдХреА рдШрдЯрдирд╛ рдХреЗ рд▓рд┐рдП рдЬрд╛рдВрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдпрд╣ рдХреНрд╡реЗрд░реА рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реИ, рдЬрд┐рд╕реЗ рдЬрд▓реНрджреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
fts=# \timing on fts=# select count(*) from mail_messages where tsv @@ to_tsquery('wrote & tattoo');
count ------- 1 (1 row) Time: 0,959 ms
рдЕрдХреЗрд▓реЗ "рд▓рд┐рдЦреЗ" рдХреА рдЦреЛрдЬ рдореЗрдВ рдЕрдзрд┐рдХ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ:
fts=# select count(*) from mail_messages where tsv @@ to_tsquery('wrote');
count -------- 231174 (1 row) Time: 2875,543 ms (00:02,876)
рдпрд╣ рдЕрдиреБрдХреВрд▓рди рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рди рдХреЗрд╡рд▓ рджреЛ рд▓реЗрдХреНрд╕реЗрдо рдХреЗ рд▓рд┐рдП, рдмрд▓реНрдХрд┐ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдХреНрд╡реЗрд░реА рдкрд░рд┐рдгрд╛рдо рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдирд╛
GIN рдкрд╣реБрдВрдЪ рд╡рд┐рдзрд┐ рдХреА рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдкрд░рд┐рдгрд╛рдо рд╣рдореЗрд╢рд╛ рдмрд┐рдЯрдореИрдк рдХреЗ рд░реВрдк рдореЗрдВ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдпрд╣ рд╡рд┐рдзрд┐ TID рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рдгрд╛рдо TID рдирд╣реАрдВ рд▓реМрдЯрд╛ рд╕рдХрддреА рд╣реИред рдпрд╣ рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ рд╣реИ, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╕рднреА рдХреНрд╡реЗрд░реА рдкреНрд▓рд╛рди рдмрд┐рдЯрдореИрдк рд╕реНрдХреИрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рдЗрд╕рд▓рд┐рдП, рд▓рд┐рдордЯ рдХреНрд▓реЙрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд╕реВрдЪрдХрд╛рдВрдХ рд╕реНрдХреИрди рдкрд░рд┐рдгрд╛рдо рдХреА рд╕реАрдорд╛ рдХрд╛рдлреА рдХреБрд╢рд▓ рдирд╣реАрдВ рд╣реИред рдСрдкрд░реЗрд╢рди рдХреА рдЕрдиреБрдорд╛рдирд┐рдд рд▓рд╛рдЧрдд рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ ("рд╕реАрдорд╛" рдиреЛрдб рдХреЗ "рд▓рд╛рдЧрдд" рдХреНрд╖реЗрддреНрд░):
fts=# explain (costs off) select * from mail_messages where tsv @@ to_tsquery('wrote') limit 1;
QUERY PLAN ----------------------------------------------------------------------------------------- Limit (cost=1283.61..1285.13 rows=1) -> Bitmap Heap Scan on mail_messages (cost=1283.61..209975.49 rows=137207) Recheck Cond: (tsv @@ to_tsquery('wrote'::text)) -> Bitmap Index Scan on mail_messages_tsv_idx (cost=0.00..1249.30 rows=137207) Index Cond: (tsv @@ to_tsquery('wrote'::text)) (5 rows)
рд▓рд╛рдЧрдд 1285.13 рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдорд╛рдирд┐рдд рд╣реИ, рдЬреЛ рдХрд┐ рдкреВрд░реЗ рдмрд┐рдЯрдореИрдк 1249.30 (рдмрд┐рдЯрдореИрдк рдЗрдВрдбреЗрдХреНрд╕ рд╕реНрдХреИрди рдиреЛрдб рдХреЗ "рд▓рд╛рдЧрдд") рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреА рд▓рд╛рдЧрдд рд╕реЗ рдереЛрдбрд╝рд╛ рдмрдбрд╝рд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдХреНрд╖рдорддрд╛ рд╣реИред рджрд╣рд▓реАрдЬ рдорд╛рди "gin_fuzzy_search_limit" рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ рдФрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╢реВрдиреНрдп рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ (рдХреЛрдИ рд╕реАрдорд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ)ред рд▓реЗрдХрд┐рди рд╣рдо рд╕реАрдорд╛ рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
fts=# set gin_fuzzy_search_limit = 1000; fts=# select count(*) from mail_messages where tsv @@ to_tsquery('wrote');
count ------- 5746 (1 row)
fts=# set gin_fuzzy_search_limit = 10000; fts=# select count(*) from mail_messages where tsv @@ to_tsquery('wrote');
count ------- 14726 (1 row)
рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрд╡реЗрд░реА рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯреА рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреИрд░рд╛рдореАрдЯрд░ рдорд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рднрд┐рдиреНрди рд╣реЛрддреА рд╣реИ (рдпрджрд┐ рдЗрдВрдбреЗрдХреНрд╕ рдПрдХреНрд╕реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рд╕реАрдорд╛ рд╕рдЦреНрдд рдирд╣реАрдВ рд╣реИ: рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реЗ рдЕрдзрд┐рдХ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдкреИрд░рд╛рдореАрдЯрд░ рдирд╛рдо рдХреЗ "рдлрдЬреА" рднрд╛рдЧ рдХреЛ рд╕рд╣реА рдард╣рд░рд╛рддрд╛ рд╣реИред
рдХреЙрдореНрдкреИрдХреНрдЯ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡
рдмрд╛рдХреА рдХреЗ рдмреАрдЪ, GIN рдЕрдиреБрдХреНрд░рдорд┐рдд рдЙрдирдХреА рдХреЙрдореНрдкреИрдХреНрдЯрдиреЗрд╕ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдпрджрд┐ рдПрдХ рдФрд░ рдПрдХ рд╣реА рд▓реЗрдХреНрд╕реЗрдо рдХрдИ рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ (рдФрд░ рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдорд╛рдорд▓рд╛ рд╣реИ), рддреЛ рдЗрд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рджреВрд╕рд░рд╛, TID рдХреЛ рдПрдХ рдСрд░реНрдбрд░ рдХрд┐рдП рдЧрдП рдлреИрд╢рди рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╣рдореЗрдВ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рдВрдкреАрдбрд╝рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдмрдирд╛рддрд╛ рд╣реИ: рд╕реВрдЪреА рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЕрдЧрд▓рд╛ TID рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдПрдХ рд╕реЗ рдЗрд╕рдХреЗ рдЕрдВрддрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддрд╛ рд╣реИ; рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдПрдХ рдЫреЛрдЯреА рд╕рдВрдЦреНрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХрдо рдмрд┐рдЯреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдХрд┐ рдПрдХ рдкреВрд░реНрдг рдЫрд╣-рдмрд╛рдЗрдЯ рдЯреАрдЖрдИрдбреАред
рдЖрдХрд╛рд░ рдХрд╛ рдЕрдВрджрд╛рдЬрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рдкрд╛рда рд╕реЗ рдмреА-рд╡реГрдХреНрд╖ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВред рд▓реЗрдХрд┐рди рдПрдХ рдирд┐рд╖реНрдкрдХреНрд╖ рддреБрд▓рдирд╛ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдирд╣реАрдВ рд╣реИ:
- GIN рдЕрд▓рдЧ-рдЕрд▓рдЧ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ ("tsvector" рдкрд░ "рдЯреЗрдХреНрд╕реНрдЯ" рдХреЗ рдмрдЬрд╛рдп рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ), рдЬреЛ рдЫреЛрдЯрд╛ рд╣реИ,
- рдЙрд╕реА рд╕рдордп, рдмреА-рдЯреНрд░реА рдХреЗ рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рд▓рдЧрднрдЧ рджреЛ рдХрд┐рд▓реЛрдмрд╛рдЗрдЯ рддрдХ рдЫреЛрдЯрд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред
рдлрд┐рд░ рднреА, рд╣рдо рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВ:
fts=# create index mail_messages_btree on mail_messages(substring(body_plain for 2048));
рд╣рдо GiST рдЗрдВрдбреЗрдХреНрд╕ рднреА рдмрдирд╛рдПрдВрдЧреЗ:
fts=# create index mail_messages_gist on mail_messages using gist(tsv);
"рд╡реИрдХреНрдпреВрдо рдлреБрд▓" рдкрд░ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд╛ рдЖрдХрд╛рд░:
fts=# select pg_size_pretty(pg_relation_size('mail_messages_tsv_idx')) as gin, pg_size_pretty(pg_relation_size('mail_messages_gist')) as gist, pg_size_pretty(pg_relation_size('mail_messages_btree')) as btree;
gin | gist | btree --------+--------+-------- 179 MB | 125 MB | 546 MB (1 row)
рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдХрд╛рд░рдг, рд╣рдо рдмрд┐рдЯрдореИрдк рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд░реВрдк рдореЗрдВ Oracle рд╕реЗ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди GIN рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╡рд┐рд╡рд░рдг рдореЗрдВ рдЬрд╛рдиреЗ рдХреЗ рдмрд┐рдирд╛, рдореИрдВ рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рджрд┐рдорд╛рдЧреЛрдВ рдХреЗ рд▓рд┐рдП
рд▓реБрдИрд╕ рдХреА рдкреЛрд╕реНрдЯ рдХрд╛ рд╕рдВрджрд░реНрдн рдкреНрд░рджрд╛рди
рдХрд░рддрд╛ рд╣реВрдВ)ред рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдмрд┐рдЯрдореИрдк рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рдирдХреЗ рдХреБрдЫ рдЕрджреНрд╡рд┐рддреАрдп рдореВрд▓реНрдп рд╣реИрдВ, рдЬреЛ GIN рдХреЗ рд▓рд┐рдП рднреА рдЙрддреНрдХреГрд╖реНрдЯ рд╣реИред рдФрд░, рдЬреИрд╕рд╛
рдХрд┐ рдкрд╣рд▓реЗ рд▓реЗрдЦ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛
рд╣реИ , PostgreSQL рдордХреНрдЦреА рдкрд░ GIN рд╕рд╣рд┐рдд рдХрд┐рд╕реА рднреА рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдмрд┐рдЯрдореИрдк рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░ рд╕рдХрддрд╛ рд╣реИред
GiST рдпрд╛ GIN?
рдХрдИ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП, рдСрдкрд░реЗрдЯрд░ рдХрдХреНрд╖рд╛рдПрдВ GiST рдФрд░ GIN рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИрдВ, рдЬреЛ рдПрдХ рдкреНрд░рд╢реНрди рдЙрдард╛рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕ рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рд╢рд╛рдпрдж, рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреБрдЫ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред
рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, GIN рд╕рдЯреАрдХрддрд╛ рдФрд░ рдЦреЛрдЬ рдХреА рдЧрддрд┐ рдореЗрдВ GiST рдзрдбрд╝рдХрддрд╛ рд╣реИред рдпрджрд┐ рдбреЗрдЯрд╛ рдХреЛ рдмрд╛рд░-рдмрд╛рд░ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рддреЗрдЬреА рд╕реЗ рдЦреЛрдЬ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рдЬреАрдЖрдИрдПрди рдПрдХ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдЧрд╛ред
рджреВрд╕рд░реА рдУрд░, рдпрджрд┐ рдбреЗрдЯрд╛ рдХреЛ рдЧрд╣рди рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ GIN рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдУрд╡рд░рд╣реЗрдб рд▓рд╛рдЧрдд рдмрд╣реБрдд рдмрдбрд╝реА рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХрддреА рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рджреЛрдиреЛрдВ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреА рд╣реЛрдЧреА рдФрд░ рд╡рд╣ рдЪреБрдирдирд╛ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рдмреЗрд╣рддрд░ рд╕рдВрддреБрд▓рд┐рдд рд╣реЛрдВред
Arrays
GIN рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдг рд╕рд░рдгрд┐рдпреЛрдВ рдХрд╛ рдЕрдиреБрдХреНрд░рдордг рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рд░рдгреА рддрддреНрд╡ рдЗрдВрдбреЗрдХреНрд╕ рдореЗрдВ рдЖрддреЗ рд╣реИрдВ, рдЬреЛ рд╕рд░рдгрд┐рдпреЛрдВ рдкрд░ рдХрдИ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:
postgres=# select amop.amopopr::regoperator, amop.amopstrategy from pg_opclass opc, pg_opfamily opf, pg_am am, pg_amop amop where opc.opcname = 'array_ops' and opf.oid = opc.opcfamily and am.oid = opf.opfmethod and amop.amopfamily = opc.opcfamily and am.amname = 'gin' and amop.amoplefttype = opc.opcintype;
amopopr | amopstrategy -----------------------+-------------- &&(anyarray,anyarray) | 1 intersection @>(anyarray,anyarray) | 2 contains array <@(anyarray,anyarray) | 3 contained in array =(anyarray,anyarray) | 4 equality (4 rows)
рд╣рдорд╛рд░реЗ
рдбреЗрдореЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЙрдбрд╝рд╛рдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде "рдорд╛рд░реНрдЧ" рджреГрд╢реНрдп рд╣реИрдВред рдмрд╛рдХреА рдХреЗ рдмреАрдЪ, рдЗрд╕ рджреГрд╢реНрдп рдореЗрдВ "рджрд┐рди_рдСрдл_рд╡реАрдХ" рдХреЙрд▓рдо рд╣реЛрддрд╛ рд╣реИ - рд╕рдкреНрддрд╛рд╣ рдХреЗ рджрд┐рдиреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдЬрдм рдЙрдбрд╝рд╛рдиреЗрдВ рд╣реЛрддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡рд╛рдиреБрдХреЛрд╡реЛ рд╕реЗ рдЧреЗрд▓реЗрдВрджрдЬрд╝рд┐рдХ рдХреА рдЙрдбрд╝рд╛рди рдордВрдЧрд▓рд╡рд╛рд░, рдЧреБрд░реБрд╡рд╛рд░ рдФрд░ рд░рд╡рд┐рд╡рд╛рд░ рдХреЛ рдирд┐рдХрд▓рддреА рд╣реИ:
demo=# select departure_airport_name, arrival_airport_name, days_of_week from routes where flight_no = 'PG0049';
departure_airport_name | arrival_airport_name | days_of_week ------------------------+----------------------+-------------- Vnukovo | Gelendzhik | {2,4,7} (1 row)
рд╕реВрдЪрдХрд╛рдВрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рджреГрд╢реНрдп рдХреЛ "рднреМрддрд┐рдХ" рдХрд░реЗрдВ:
demo=# create table routes_t as select * from routes; demo=# create index on routes_t using gin(days_of_week);
рдЕрдм рд╣рдо рд╕рднреА рдЙрдбрд╝рд╛рдиреЛрдВ рдХреЛ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдордВрдЧрд▓рд╡рд╛рд░, рдЧреБрд░реБрд╡рд╛рд░ рдФрд░ рд░рд╡рд┐рд╡рд╛рд░ рдХреЛ рдирд┐рдХрд▓рддреА рд╣реИрдВ:
demo=# explain (costs off) select * from routes_t where days_of_week = ARRAY[2,4,7];
QUERY PLAN ----------------------------------------------------------- Bitmap Heap Scan on routes_t Recheck Cond: (days_of_week = '{2,4,7}'::integer[]) -> Bitmap Index Scan on routes_t_days_of_week_idx Index Cond: (days_of_week = '{2,4,7}'::integer[]) (4 rows)
рдРрд╕рд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдЫрд╣ рд╣реИрдВ:
demo=# select flight_no, departure_airport_name, arrival_airport_name, days_of_week from routes_t where days_of_week = ARRAY[2,4,7];
flight_no | departure_airport_name | arrival_airport_name | days_of_week -----------+------------------------+----------------------+-------------- PG0005 | Domodedovo | Pskov | {2,4,7} PG0049 | Vnukovo | Gelendzhik | {2,4,7} PG0113 | Naryan-Mar | Domodedovo | {2,4,7} PG0249 | Domodedovo | Gelendzhik | {2,4,7} PG0449 | Stavropol | Vnukovo | {2,4,7} PG0540 | Barnaul | Vnukovo | {2,4,7} (6 rows)
рдпрд╣ рдХреНрд╡реЗрд░реА рдХреИрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ? рдареАрдХ рдЙрд╕реА рддрд░рд╣ рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╣реИ:
- рд╕рд░рдгреА {2,4,7} рд╕реЗ, рдЬреЛ рдпрд╣рд╛рдВ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИ, рддрддреНрд╡реЛрдВ (рдЦреЛрдЬ рдХреАрд╡рд░реНрдб) рдХреЛ рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдпреЗ "2", "4" рдФрд░ "7" рдХреЗ рдореВрд▓реНрдп рд╣реИрдВред
- рддрддреНрд╡реЛрдВ рдХреЗ рдкреЗрдбрд╝ рдореЗрдВ, рдирд┐рдХрд╛рд▓реЗ рдЧрдП рдХреБрдВрдЬреА рдкрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП TID рдХреА рд╕реВрдЪреА рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
- рдкрд╛рдП рдЧрдП рд╕рднреА TID рдореЗрдВ рд╕реЗ, рд╕рдВрдЧрддрд┐ рдлрд╝рдВрдХреНрд╢рди рдЙрди рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХреНрд╡реЗрд░реА рд╕реЗ рдСрдкрд░реЗрдЯрд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред
=
рдСрдкрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП, рдХреЗрд╡рд▓ рдЙрди TID рдХрд╛ рдорд┐рд▓рд╛рди рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рддреАрдиреЛрдВ рд╕реВрдЪрд┐рдпреЛрдВ рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВ (рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рд░рдгреА рдореЗрдВ рд╕рднреА рддрддреНрд╡ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП)ред рд▓реЗрдХрд┐рди рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ: рдпрд╣ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдФрд░ рд╣рдо рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд╕рд╛рде рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдкрд╣реБрдБрдЪ рд╡рд┐рдзрд┐ рдЕрдиреБрдХреНрд░рдордг рдЗрдВрдЬрди рдХреЛ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд╕рд╛рде рд▓реМрдЯреЗ рд╕рднреА TID рдХреЛ рдлрд┐рд░ рд╕реЗ рдЬрд╛рдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рддреА рд╣реИред
рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рд╡рд╣рд╛рдБ рд░рдгрдиреАрддрд┐рдпрд╛рдБ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, "рд╕рд░рдгреА рдореЗрдВ рдирд┐рд╣рд┐рдд") рдЬреЛ рдХреБрдЫ рднреА рдЬрд╛рдВрдЪ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреА рд╣реИ рдФрд░ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд╕рд╛рде рдкрд╛рдП рдЧрдП рд╕рднреА TID рдХреЛ рдлрд┐рд░ рд╕реЗ рдЬрд╛рдБрдЪрдирд╛ рд╣реЛрдЧрд╛ред
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдХрд░реЗрдВ рдпрджрд┐ рд╣рдореЗрдВ рдордВрдЧрд▓рд╡рд╛рд░, рдЧреБрд░реБрд╡рд╛рд░ рдФрд░ рд░рд╡рд┐рд╡рд╛рд░ рдХреЛ рдорд╛рд╕реНрдХреЛ рд╕реЗ рд░рд╡рд╛рдирд╛ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рдЙрдбрд╝рд╛рдиреЛрдВ рдХреЛ рдЬрд╛рдирдирд╛ рд╣реИ? рд╕реВрдЪрдХрд╛рдВрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рдЬреЛ "рдлрд╝рд┐рд▓реНрдЯрд░" рдХреЙрд▓рдо рдореЗрдВ рдорд┐рд▓реЗрдЧрд╛ред
demo=# explain (costs off) select * from routes_t where days_of_week = ARRAY[2,4,7] and departure_city = 'Moscow';
QUERY PLAN ----------------------------------------------------------- Bitmap Heap Scan on routes_t Recheck Cond: (days_of_week = '{2,4,7}'::integer[]) Filter: (departure_city = 'Moscow'::text) -> Bitmap Index Scan on routes_t_days_of_week_idx Index Cond: (days_of_week = '{2,4,7}'::integer[]) (5 rows)
рдпрд╣рд╛рдВ рдпрд╣ рдареАрдХ рд╣реИ (рд╕реВрдЪрдХрд╛рдВрдХ рд╡реИрд╕реЗ рднреА рдХреЗрд╡рд▓ рдЫрд╣ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ), рд▓реЗрдХрд┐рди рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЬрд╣рд╛рдВ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрдерд┐рддрд┐ рдЪрдпрдирд╛рддреНрдордХ рдХреНрд╖рдорддрд╛ рдХреЛ рдмрдврд╝рд╛рддреА рд╣реИ, рдРрд╕реЗ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рд╡рд╛рдВрдЫрд┐рдд рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдо рдХреЗрд╡рд▓ рдЗрдВрдбреЗрдХреНрд╕ рдирд╣реАрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:
demo=# create index on routes_t using gin(days_of_week,departure_city);
ERROR: data type text has no default operator class for access method "gin" HINT: You must specify an operator class for the index or define a default operator class for the data type.
рд▓реЗрдХрд┐рди "
btree_gin " рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдорджрдж рдХрд░реЗрдЧрд╛, рдЬреЛ GIN рдСрдкрд░реЗрдЯрд░ рдХрдХреНрд╖рд╛рдПрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдирд┐рдпрдорд┐рдд рдмреА-рдЯреНрд░реА рдХреЗ рдХрд╛рдо рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рддреЗ рд╣реИрдВред
demo=# create extension btree_gin; demo=# create index on routes_t using gin(days_of_week,departure_city); demo=# explain (costs off) select * from routes_t where days_of_week = ARRAY[2,4,7] and departure_city = 'Moscow';
QUERY PLAN --------------------------------------------------------------------- Bitmap Heap Scan on routes_t Recheck Cond: ((days_of_week = '{2,4,7}'::integer[]) AND (departure_city = 'Moscow'::text)) -> Bitmap Index Scan on routes_t_days_of_week_departure_city_idx Index Cond: ((days_of_week = '{2,4,7}'::integer[]) AND (departure_city = 'Moscow'::text)) (4 rows)
JSONB
рдПрдХ рдпреМрдЧрд┐рдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдЬрд┐рд╕рдореЗрдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд GIN рд╕рдорд░реНрдерди рд╣реИ JSONред JSON рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдИ рдСрдкрд░реЗрдЯрд░реЛрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
postgres=# select opc.opcname, amop.amopopr::regoperator, amop.amopstrategy as str from pg_opclass opc, pg_opfamily opf, pg_am am, pg_amop amop where opc.opcname in ('jsonb_ops','jsonb_path_ops') and opf.oid = opc.opcfamily and am.oid = opf.opfmethod and amop.amopfamily = opc.opcfamily and am.amname = 'gin' and amop.amoplefttype = opc.opcintype;
opcname | amopopr | str ----------------+------------------+----- jsonb_ops | ?(jsonb,text) | 9 top-level key exists jsonb_ops | ?|(jsonb,text[]) | 10 some top-level key exists jsonb_ops | ?&(jsonb,text[]) | 11 all top-level keys exist jsonb_ops | @>(jsonb,jsonb) | 7 JSON value is at top level jsonb_path_ops | @>(jsonb,jsonb) | 7 (5 rows)
рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рджреЛ рдСрдкрд░реЗрдЯрд░ рдХрдХреНрд╖рд╛рдПрдВ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ: "jsonb_ops" рдФрд░ "jsonb_path_ops"ред
рдкрд╣рд▓рд╛ рдСрдкрд░реЗрдЯрд░ рд╡рд░реНрдЧ "jsonb_ops" рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкреНрд░рд╛рд░рдВрднрд┐рдХ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЗ рддрддреНрд╡реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рднреА рдХреБрдВрдЬрд┐рдпрд╛рдБ, рдорд╛рди рдФрд░ рд╕рд░рдгреА рддрддреНрд╡ рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рдорд┐рд▓рддреЗ рд╣реИрдВред рдЗрди рддрддреНрд╡реЛрдВ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЬреЛрдбрд╝реА рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рддрддреНрд╡ рдПрдХ рдХреБрдВрдЬреА рд╣реИ (рдпрд╣ "рдореМрдЬреВрдж" рд░рдгрдиреАрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬреЛ рдХреБрдВрдЬрд┐рдпреЛрдВ рдФрд░ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рдХрд░рддреЗ рд╣реИрдВ)ред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП JSON рдХреЗ рд░реВрдк рдореЗрдВ "рдорд╛рд░реНрдЧреЛрдВ" рд╕реЗ рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВ:
demo=# create table routes_jsonb as select to_jsonb(t) route from ( select departure_airport_name, arrival_airport_name, days_of_week from routes order by flight_no limit 4 ) t; demo=# select ctid, jsonb_pretty(route) from routes_jsonb;
ctid | jsonb_pretty -------+------------------------------------------------- (0,1) | { + | "days_of_week": [ + | 1 + | ], + | "arrival_airport_name": "Surgut", + | "departure_airport_name": "Ust-Ilimsk" + | } (0,2) | { + | "days_of_week": [ + | 2 + | ], + | "arrival_airport_name": "Ust-Ilimsk", + | "departure_airport_name": "Surgut" + | } (0,3) | { + | "days_of_week": [ + | 1, + | 4 + | ], + | "arrival_airport_name": "Sochi", + | "departure_airport_name": "Ivanovo-Yuzhnyi"+ | } (0,4) | { + | "days_of_week": [ + | 2, + | 5 + | ], + | "arrival_airport_name": "Ivanovo-Yuzhnyi", + | "departure_airport_name": "Sochi" + | } (4 rows)
demo=# create index on routes_jsonb using gin(route);
рд╕реВрдЪрдХрд╛рдВрдХ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ:

рдЕрдм, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣ рдПрдХ рдХреНрд╡реЗрд░реА, рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
demo=# explain (costs off) select jsonb_pretty(route) from routes_jsonb where route @> '{"days_of_week": [5]}';
QUERY PLAN --------------------------------------------------------------- Bitmap Heap Scan on routes_jsonb Recheck Cond: (route @> '{"days_of_week": [5]}'::jsonb) -> Bitmap Index Scan on routes_jsonb_route_idx Index Cond: (route @> '{"days_of_week": [5]}'::jsonb) (4 rows)
JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреА рдЬрдбрд╝ рд╕реЗ рд╢реБрд░реВ,
@>
рдСрдкрд░реЗрдЯрд░ рдпрд╣ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдорд╛рд░реНрдЧ (
"days_of_week": [5]
рд╣реЛрддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдХреНрд╡реЗрд░реА рдПрдХ рдкрдВрдХреНрддрд┐ рд▓реМрдЯреЗрдЧреА:
demo=# select jsonb_pretty(route) from routes_jsonb where route @> '{"days_of_week": [5]}';
jsonb_pretty ------------------------------------------------ { + "days_of_week": [ + 2, + 5 + ], + "arrival_airport_name": "Ivanovo-Yuzhnyi",+ "departure_airport_name": "Sochi" + } (1 row)
рдХреНрд╡реЗрд░реА рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХреА рдЬрд╛рддреА рд╣реИ:
- рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдореЗрдВ (
"days_of_week": [5]
) рддрддреНрд╡ (рдЦреЛрдЬ рдХреБрдВрдЬреА) рдирд┐рдХрд╛рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ: "days_of_week" рдФрд░ "5"ред
- рддрддреНрд╡реЛрдВ рдХреА рдкреЗрдбрд╝ рдореЗрдВ рдирд┐рдХрд╛рд▓реА рдЧрдИ рдЪрд╛рдмрд┐рдпрд╛рдВ рдкрд╛рдИ рдЬрд╛рддреА рд╣реИрдВ, рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП TIDs рдХреА рд╕реВрдЪреА рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: "5" - (0.4) рдХреЗ рд▓рд┐рдП, рдФрд░ "рджрд┐рдиреЛрдВ_рдлреЛрдХ" рдХреЗ рд▓рд┐рдП - (0,1), (0,2) ), (0.3), (0.4)ред
- рдкрд╛рдП рдЧрдП рд╕рднреА TID рдореЗрдВ рд╕реЗ, рд╕рдВрдЧрддрд┐ рдлрд╝рдВрдХреНрд╢рди рдЙрди рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХреНрд╡реЗрд░реА рд╕реЗ рдСрдкрд░реЗрдЯрд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред
@>
рдСрдкрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП, рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рд╕реЗ рд╕рднреА рддрддреНрд╡ рдирд╣реАрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдХреЗрд╡рд▓ (0,4) рдмрдЪрд╛ рд╣реБрдЖ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдЕрднреА рднреА рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд╕рд╛рде рдЫреЛрдбрд╝реЗ рдЧрдП TID рдХреЛ рдлрд┐рд░ рд╕реЗ рдЬрд╛рдБрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЗрдВрдбреЗрдХреНрд╕ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдХреМрди рд╕реЗ рддрддреНрд╡ рдкрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВред
рдЕрдиреНрдп рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк
рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
JSON рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рдВрдкрд░рд┐рдХ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдЕрд▓рд╛рд╡рд╛, "jsquery" рд╡рд┐рд╕реНрддрд╛рд░ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдЬреЛ рдХрд┐ рд╕рдореГрджреНрдз рдХреНрд╖рдорддрд╛рдУрдВ (рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, GIN рдЕрдиреБрдХреНрд░рдорд┐рдд рдХреЗ рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде) рдХреЗ рд╕рд╛рде рдПрдХ рдХреНрд╡реЗрд░реА рднрд╛рд╖рд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, 2016 рдореЗрдВ, рдПрдХ рдирдпрд╛ SQL рдорд╛рдирдХ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдФрд░ рдХреНрд╡реЗрд░реА рднрд╛рд╖рд╛ "SQL / JSON рдкрде" рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдирдХ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд╣рд▓реЗ рд╣реА рдкреВрд░рд╛ рд╣реЛ рдЪреБрдХрд╛ рд╣реИ, рдФрд░ рд╣рдореЗрдВ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдпрд╣ PostgreSQL 11 рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред
SQL / JSON рдкрде рдкреИрдЪ рдЕрдВрддрддрдГ PostgreSQL 12 рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрджреНрдз рдерд╛, рдЬрдмрдХрд┐ рдЕрдиреНрдп рдЯреБрдХрдбрд╝реЗ рдЕрднреА рднреА рд░рд╛рд╕реНрддреЗ рдореЗрдВ рд╣реИрдВред рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд╣рдо PostgreSQL 13 рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рд╕реБрд╡рд┐рдзрд╛ рджреЗрдЦреЗрдВрдЧреЗред
internals
рд╣рдо "
рдкреЗрдЬрд┐рдВрд╕реНрдкреЗрдХреНрдЯ " рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ GIN рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рдЕрдВрджрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
fts=# create extension pageinspect;
рдореЗрдЯрд╛ рдкреГрд╖реНрда рдХреА рдЬрд╛рдирдХрд╛рд░реА рд╕рд╛рдорд╛рдиреНрдп рдЖрдБрдХрдбрд╝реЗ рджрд┐рдЦрд╛рддреА рд╣реИ:
fts=# select * from gin_metapage_info(get_raw_page('mail_messages_tsv_idx',0));
-[ RECORD 1 ]----+----------- pending_head | 4294967295 pending_tail | 4294967295 tail_free_size | 0 n_pending_pages | 0 n_pending_tuples | 0 n_total_pages | 22968 n_entry_pages | 13751 n_data_pages | 9216 n_entries | 1423598 version | 2
рдкреГрд╖реНрда рд╕рдВрд░рдЪрдирд╛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдХреНрд╖реЗрддреНрд░ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ рдЬрд╣рд╛рдВ рдкрд╣реБрдВрдЪ рд╡рд┐рдзрд┐рдпрд╛рдВ рдЙрдирдХреА рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреА рд╣реИрдВ; рдпрд╣ рдХреНрд╖реЗрддреНрд░ рдирд┐рд░реНрд╡рд╛рдд рдЬреИрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЗ рд▓рд┐рдП "рдЕрдкрд╛рд░рджрд░реНрд╢реА" рд╣реИред "Gin_page_opaque_info" рдлрд╝рдВрдХреНрд╢рди GIN рдХреЗ рд▓рд┐рдП рдпрд╣ рдбреЗрдЯрд╛ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реВрдЪрдХрд╛рдВрдХ рдкреГрд╖реНрдареЛрдВ рдХреЗ рд╕реЗрдЯ рдХреЛ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ:
fts=# select flags, count(*) from generate_series(1,22967) as g(id),
flags | count ------------------------+------- {meta} | 1 meta page {} | 133 internal page of element B-tree {leaf} | 13618 leaf page of element B-tree {data} | 1497 internal page of TID B-tree {data,leaf,compressed} | 7719 leaf page of TID B-tree (5 rows)
"Gin_leafpage_items" рдлрд╝рдВрдХреНрд╢рди рдкреГрд╖реНрдареЛрдВ рдкрд░ рд╕рдВрдЧреНрд░рд╣реАрдд TID рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ {рдбреЗрдЯрд╛, рдкрддреНрддреА, рд╕рдВрдкреАрдбрд┐рдд}:
fts=# select * from gin_leafpage_items(get_raw_page('mail_messages_tsv_idx',2672));
-[ RECORD 1 ]--------------------------------------------------------------------- first_tid | (239,44) nbytes | 248 tids | {"(239,44)","(239,47)","(239,48)","(239,50)","(239,52)","(240,3)",... -[ RECORD 2 ]--------------------------------------------------------------------- first_tid | (247,40) nbytes | 248 tids | {"(247,40)","(247,41)","(247,44)","(247,45)","(247,46)","(248,2)",... ...
рдпрд╣рд╛рдВ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ TID рдХреЗ рд╡реГрдХреНрд╖ рдХреЗ рдкреГрд╖реНрда рдЫреЛрдбрд╝ рджреЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдмрд┐рдВрджреБрдУрдВ рдХреА рдмрдЬрд╛рдп рддрд╛рд▓рд┐рдХрд╛ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рдЫреЛрдЯреА рд╕рдВрдХреБрдЪрд┐рдд рд╕реВрдЪреА рд╣реЛрддреА рд╣реИред
рдЧреБрдг
рдЖрдЗрдП GIN рдкрд╣реБрдВрдЪ рд╡рд┐рдзрд┐ рдХреЗ рдЧреБрдгреЛрдВ рдХреЛ рджреЗрдЦреЗрдВ (рдкреНрд░рд╢реНрди
рдкрд╣рд▓реЗ рд╣реА рдкреНрд░рджрд╛рди рдХрд┐рдП рдЬрд╛ рдЪреБрдХреЗ рд╣реИрдВ )ред
amname | name | pg_indexam_has_property --------+---------------+------------------------- gin | can_order | f gin | can_unique | f gin | can_multi_col | t gin | can_exclude | f
рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдЬреАрдЖрдИрдПрди рдмрд╣реБрд░рдВрдЧреА рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рдУрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдирд┐рдпрдорд┐рдд рдмреА-рдкреЗрдбрд╝ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдпреМрдЧрд┐рдХ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рдмрдЬрд╛рдп, рдПрдХ рдмрд╣реБрд░рдВрдЧреА рд╕реВрдЪрдХрд╛рдВрдХ рдЕрднреА рднреА рд╡реНрдпрдХреНрддрд┐рдЧрдд рддрддреНрд╡реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рдХреЙрд▓рдо рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реВрдЪрдХрд╛рдВрдХ-рдкрд░рдд рдЧреБрдг рдЙрдкрд▓рдмреНрдз рд╣реИрдВ:
name | pg_index_has_property ---------------+----------------------- clusterable | f index_scan | f bitmap_scan | t backward_scan | f
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ TID (рдЗрдВрдбреЗрдХреНрд╕ рд╕реНрдХреИрди) рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рдиреЗ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ; рдХреЗрд╡рд▓ рдмрд┐рдЯрдореИрдк рд╕реНрдХреИрди рд╕рдВрднрд╡ рд╣реИред
рдмреИрдХрд╡рд░реНрдб рд╕реНрдХреИрди рднреА рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ: рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдХреЗрд╡рд▓ рдЗрдВрдбреЗрдХреНрд╕ рд╕реНрдХреИрди рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд┐рдЯрдореИрдк рд╕реНрдХреИрди рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред
рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрддрдВрдн-рдкрд░рдд рдЧреБрдг рд╣реИрдВ:
name | pg_index_column_has_property --------------------+------------------------------ asc | f desc | f nulls_first | f nulls_last | f orderable | f distance_orderable | f returnable | f search_array | f search_nulls | f
рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИ: рдХреЛрдИ рдЫрдБрдЯрд╛рдИ рдирд╣реАрдВ рд╣реИ (рдЬреЛ рд╕реНрдкрд╖реНрдЯ рд╣реИ), рдХрд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдХреЛрдИ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рд╣реИ (рдЪреВрдВрдХрд┐ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕реНрд╡рдпрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдирд╣реАрдВ рд╣реИ), рдирд▓ рдХрд╛ рдХреЛрдИ рд╣реЗрд░рдлреЗрд░ (рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдпреМрдЧрд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рддрддреНрд╡реЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ) ред
рдЕрдиреНрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░
рдХреБрдЫ рдФрд░ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдЙрдкрд▓рдмреНрдз рд╣реИрдВ рдЬреЛ рдХреБрдЫ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП GIN рдХрд╛ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред
- " pg_trgm " рд╣рдореЗрдВ рд╢рдмреНрджреЛрдВ рдХреА "рд╕рдорд╛рдирддрд╛" рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдмрдирд╛рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рддрдиреЗ рд╕рдорд╛рди рддреАрди-рдЕрдХреНрд╖рд░ рдЕрдиреБрдХреНрд░рдо (рдЯреНрд░рд┐рдЧрд░реНрд╕) рдЙрдкрд▓рдмреНрдз рд╣реИрдВред рджреЛ рдСрдкрд░реЗрдЯрд░ рдХрдХреНрд╖рд╛рдПрдВ рдЬреЛрдбрд╝реА рдЬрд╛рддреА рд╣реИрдВ, "gist_trgm_ops" рдФрд░ "gin_trgm_ops", рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рдСрдкрд░реЗрдЯрд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ LIKE рдФрд░ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд╛рдзрдиреЛрдВ рдХреА рддреБрд▓рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рдЯрд╛рдЗрдкреЛрд╕ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢рдмреНрдж рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ рдХреЗ рд╕рд╛рде рдЗрд╕ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
- " hstore " "key-value" рд╕реНрдЯреЛрд░реЗрдЬ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП, рд╡рд┐рднрд┐рдиреНрди рдПрдХреНрд╕реЗрд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдСрдкрд░реЗрдЯрд░ рдХрдХреНрд╖рд╛рдПрдВ GIN рд╕рд╣рд┐рдд рдЙрдкрд▓рдмреНрдз рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, "рдЬреЛрдВрд╕рдм" рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреА рд╢реБрд░реБрдЖрдд рдХреЗ рд╕рд╛рде, "рд╣рд╕реНрдЯреЛрд░" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╡рд┐рд╢реЗрд╖ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реИрдВред
- " рдЗрдВрдЯреНрд░реИрд░реЗ " рдкреВрд░реНрдгрд╛рдВрдХ рд╕рд░рдгрд┐рдпреЛрдВ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдЗрдВрдбреЗрдХреНрд╕ рд╕рдкреЛрд░реНрдЯ рдореЗрдВ GiST, рд╕рд╛рде рд╣реА GIN ("gin__int_ops" рдСрдкрд░реЗрдЯрд░ рдХреНрд▓рд╛рд╕) рд╢рд╛рдорд┐рд▓ рд╣реИред
рдФрд░ рдЗрди рджреЛрдиреЛрдВ рдПрдХреНрд╕рдЯреЗрдВрд╢рдиреЛрдВ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдкрд╣рд▓реЗ рд╣реА рдХрд┐рдпрд╛ рдЬрд╛ рдЪреБрдХрд╛ рд╣реИ:
- " btree_gin " рдирд┐рдпрдорд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП GIN рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдмрд╣реБ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдореЗрдВ рдХрдВрдкрд╛рдЙрдВрдб рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред
- " jsquery " JSON рдХреНрд╡реЗрд░реА рдХреЗ рд▓рд┐рдП рдПрдХ рднрд╛рд╖рд╛ рдФрд░ рдЗрд╕ рднрд╛рд╖рд╛ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдПрдХ рдСрдкрд░реЗрдЯрд░ рд╡рд░реНрдЧ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдПрдХ рдорд╛рдирдХ PostgreSQL рд╡рд┐рддрд░рдг рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИред
рдкрд░ рдкрдврд╝реЗрдВ ред