
рдХрд░реНрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдореЛрд░реА рдХреЛ рдмрд░реНрдмрд╛рдж рдХрд┐рдП рдмрд┐рдирд╛ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрдм рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдмрд╛рд░ рдПрдХ рд╕рдорд╛рди рдХрд╛рд░реНрдп рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рд╣реИ, рдФрд░ рдореЗрд░реЗ рд╕рд╛рдордиреЗ рд╕рд┐рд░реНрдл рдПрдХ рдмрд╛рд░ рдирд╣реАрдВред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХрд░реНрд╕рд░ рдХрд┐рди рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдореИрдВ PostrgeSQL рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ PHP + Doctrine рд╕реЗ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдХреЛрдб рджреЗ рджреВрдВрдЧрд╛ред
рд╕рдорд╕реНрдпрд╛
рдЖрдЗрдП рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ PHP рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ, рдЬреЛ рдмрдбрд╝реА рдФрд░ рднрд╛рд░реА рд╣реИред рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдпрд╣ рдХреБрдЫ рдврд╛рдВрдЪреЗ рдХреА рдорджрдж рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рд┐рдореНрдлрдиреАред рдпрд╣ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, PostgreSQL, рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдСрд░реНрдбрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд╕рд╛рде 2,000,000 рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд▓реЗрдЯ рд╣реИред рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реНрд╡рдпрдВ рдЗрди рдЖрджреЗрд╢реЛрдВ рдХрд╛ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИ, рдЬреЛ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдФрд░ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдФрд░, рдореБрдЭреЗ рдХрд╣рдиреЗ рджреЛ, рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдХрд░ рд░рд╣рд╛ рд╣реИред
рдЕрдм рд╣рдорд╕реЗ рдкреВрдЫрд╛ рдЧрдпрд╛ (рдХреНрдпрд╛ рдЖрдкрд╕реЗ рдЕрднреА рддрдХ рдирд╣реАрдВ рдкреВрдЫрд╛ рдЧрдпрд╛ рд╣реИ? рдЙрдиреНрд╣реЗрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдкреВрдЫрд╛ рдЬрд╛рдПрдЧрд╛) рдПрдХреНрд╕реЗрд▓ рдлрд╛рдЗрд▓ рдореЗрдВ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдСрд░реНрдбрд░ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЖрдЗрдП рдПрдХ рдЯреЗрдмрд▓ рдЖрдЗрдХрди рдХреЗ рд╕рд╛рде рдПрдХ рдмрдЯрди рдХреЛ рдХреЛрдбрд╝рд╛, рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЖрджреЗрд╢ рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдереВрдХ рджреЗрдЧрд╛ред
рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдХреИрд╕реЗ рддрдп рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдЦрд░рд╛рдм рдХреНрдпреЛрдВ рд╣реИ?
рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреИрд╕реЗ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдиреЗ рдЕрднреА рддрдХ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдп рдХрд╛ рд╕рд╛рдордирд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред рд╡рд╣ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ SELECT рдХрд░рддрд╛ рд╣реИ, рдХреНрд╡реЗрд░реА рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛ рдПрдХреНрд╕реЗрд▓ рдлрд╛рдЗрд▓ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рджреЗрддрд╛ рд╣реИред рдХрд╛рд░реНрдп рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдкрд░реАрдХреНрд╖рдг рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рджрди рдореЗрдВ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИрдВред
рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╣рдордиреЗ PHP рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЙрдЪрд┐рдд (рдпрдХреАрдирди) рдкреНрд░рддрд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ 1 рдЬреАрдмреА рдХреА рдореЗрдореЛрд░реА рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рд╣реИ, рдФрд░ рдЬреИрд╕реЗ рд╣реА рдпреЗ 2 рдорд┐рд▓рд┐рдпрди рд▓рд╛рдЗрдиреЗрдВ рдЕрдм рдЗрд╕ рдЧреАрдЧрд╛рдмрд╛рдЗрдЯ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИрдВ, рд╕рдм рдХреБрдЫ рдЯреВрдЯ рдЬрд╛рддрд╛ рд╣реИред PHP рдПрдХ "рдореЗрдореЛрд░реА рд╕реЗ рдмрд╛рд╣рд░" рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдХреНрд░реИрд╢ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╢рд┐рдХрд╛рдпрдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдирд╣реАрдВ рд╣реБрдИ рд╣реИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реЛрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рдЕрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╣реБрдд рд╣реА рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдЪреБрдирд╛ рд╣реИ - рдЙрди рд╕рднреА рдХреЛ рдкрд╣рд▓реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдореЛрд░реА (рдФрд░ рдЗрд╕рдХреЗ рддрд╣рдд рдбрд┐рд╕реНрдХ) рд╕реЗ PHP рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рд░реИрдо рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдбреЗрдЯрд╛ рд╣рдореЗрд╢рд╛ рдореЗрдореЛрд░реА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддрд╛ рд╣реИ, рдЖрдкрдХреЛ рдЗрд╕реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рд▓реЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 10,000 рд░рд┐рдХреЙрд░реНрдб рдкрдврд╝реЗ рдЧрдП, рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдП рдЧрдП, рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП, рдФрд░ рдХрдИ рдмрд╛рд░ред
рдареАрдХ рд╣реИ, рдЙрд╕ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реА рдмрд╛рд░ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдп рд╕реЗ рдорд┐рд▓рд╛ рдерд╛ред рдлрд┐рд░ рдореИрдВ рдПрдХ рд▓реВрдк рдмрдирд╛рдКрдВрдЧрд╛ рдФрд░ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рдХреНрд╡реЗрд░реА рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдмрдЪрд╛рд╡ рдХрд░реВрдБрдЧрд╛, рдЬреЛ рд▓рд┐рдорд┐рдЯ рдФрд░ рдУрдПрдлрдПрд╕рдИрдЯреАрдЯреА рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╣реБрдд рдорд╣рдВрдЧрд╛ рдСрдкрд░реЗрд╢рди рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП рд░рд┐рдкреЛрд░реНрдЯ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдореЗрдВ 30 рд╕реЗрдХрдВрдб рдирд╣реАрдВ рд▓рдЧрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди 30 рдорд┐рдирдЯ (рдпрд╣ рдЗрддрдирд╛ рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИ!)ред рд╡реИрд╕реЗ, рдЕрдЧрд░ рдЗрд╕ рд╕рдордп OFFSET рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рджрд┐рдорд╛рдЧ рдореЗрдВ рдЬреНрдпрд╛рджрд╛ рдХреБрдЫ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ, рддреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рд░реИрдк рдХрд┐рдП рдмрд┐рдирд╛ рд╣реА рдЗрд╕реЗ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВ ред
рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕реНрд╡рдпрдВ рд╕реЗ рдбреЗрдЯрд╛ рдХреЛ рдкрдврд╝рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ - рдХрд░реНрд╕рд░ред
рдХрд░реНрд╕рд░
рдПрдХ рдХрд░реНрд╕рд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд░рд╣рдиреЗ рд╡рд╛рд▓реЗ рдХреНрд╡реЗрд░реА рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдореЗрдВ рдПрдХ рдкрдВрдХреНрддрд┐ рдХрд╛ рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИред рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдбреЗрдЯрд╛ рдХреЛ рддреБрд░рдВрдд рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдореЛрдб рдореЗрдВ рдирд╣реАрдВ рдЪрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рдЪрдпрди рдХреЗ рд╕рд╛рде рдХрд░реНрд╕рд░ рдЦреЛрд▓реЗрдВред рдЕрдЧрд▓рд╛, рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╡рд╛рд╣ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдХрд░реНрд╕рд░ рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реИред рдпрд╣ рд╣рдореЗрдВ рдПрдХ рд╣реА рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ: рд╣рдо рдбреЗрдЯрд╛ рдХреЛ рднрд╛рдЧрд╡рдд рд░реВрдк рд╕реЗ рдкрдврд╝рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдбреЗрдЯрд╛рдмреЗрд╕ рдЙрд╕ рд▓рд╛рдЗрди рдХреЛ рдЦреЛрдЬрдиреЗ рдХрд╛ рдПрдХ рд╣реА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдЗрд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ OFFSET рдХреЗ рд╕рд╛рде рд╣реЛрддрд╛ рд╣реИред
рдХрд░реНрд╕рд░ рдХреЗрд╡рд▓ рд▓реЗрди-рджреЗрди рдХреЗ рдЕрдВрджрд░ рдЦреЛрд▓рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рддрдм рддрдХ рд░рд╣рддрд╛ рд╣реИ рдЬрдм рддрдХ рд▓реЗрдирджреЗрди рдЬреАрд╡рд┐рдд рд╣реИ (рдПрдХ рдЕрдкрд╡рд╛рдж рд╣реИ, рд╣реЛрд▓реНрдб рдХреЗ рд╕рд╛рде рджреЗрдЦреЗрдВ)ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╣рдо рдзреАрд░реЗ-рдзреАрд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдбреЗрдЯрд╛ рдкрдврд╝рддреЗ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд▓рдВрдмрд╛ рд▓реЗрдирджреЗрди рд╣реЛрдЧрд╛ред рдпрд╣ рдХрднреА-рдХрднреА рдмреБрд░рд╛ рд╣реЛрддрд╛ рд╣реИ , рдЖрдкрдХреЛ рдЗрд╕ рдЬреЛрдЦрд┐рдо рдХреЛ рд╕рдордЭрдиреЗ рдФрд░ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдбреЙрдХреНрдЯреНрд░рд┐рди рдореЗрдВ рдХрд░реНрд╕рд░
рдЖрдЗрдП рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдХрд░реНрд╕рд░ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ?
BEGIN; DECLARE mycursor1 CURSOR FOR ( SELECT * FROM huge_table );
DECLARE рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЪрдпрди рдХреНрд╡реЗрд░реА рдХреЗ рд▓рд┐рдП рдХрд░реНрд╕рд░ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЦреЛрд▓рддрд╛ рд╣реИред рдХрд░реНрд╕рд░ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдЗрд╕рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝рдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
FETCH FORWARD 10000 FROM mycursor1; < 10 000 > FETCH FORWARD 10000 FROM mycursor1; < 10 000 > ...
рдФрд░ рдЗрд╕реА рддрд░рд╣, рдЬрдм рддрдХ FETCH рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рдирд╣реАрдВ рджреЗрддрд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реЛрдЧрд╛ рдХрд┐ рдЙрдиреНрд╣реЛрдВрдиреЗ рдЕрдВрдд рддрдХ рд╕реНрдХреНрд░реЙрд▓ рдХрд┐рдпрд╛ред
COMMIT;
рд╣рдо рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рдПрдХ рд╡рд░реНрдЧ рдХреЛ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдХрд░реНрд╕рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рдЕрдВрдЬрд╛рдо рджреЗрдЧрд╛ред рдФрд░ 20% рд╕рдордп рдореЗрдВ 80% рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП , рдпрд╣ рдХреЗрд╡рд▓ рдореВрд▓ рдирд┐рд╡рд╛рд╕реА рдХреНрд╡реЗрд░реА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рддреЛ рдЪрд▓рд┐рдП рдЗрд╕реЗ PgSqlNativeQueryCursor рдХрд╣рддреЗ рд╣реИрдВред
рдбрд┐рдЬрд╛рдЗрдирд░:
public function __construct(NativeQuery $query) { $this->query = $query; $this->connection = $query->getEntityManager()->getConnection(); $this->cursorName = uniqid('cursor_'); assert($this->connection->getDriver() instanceof PDOPgSqlDriver); }
рдпрд╣рд╛рдВ рдореИрдВ рднрд╡рд┐рд╖реНрдп рдХреЗ рдХрд░реНрд╕рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд╛рдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реВрдВред
рдЪреВрдБрдХрд┐ рдХрдХреНрд╖рд╛ рдореЗрдВ PostgreSQL-рд╡рд┐рд╢рд┐рд╖реНрдЯ SQL рдХреЛрдб рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЬрд╛рдБрдЪрдирд╛ рдмреЗрд╣рддрд░ рд╣реИ рдХрд┐ рд╣рдорд╛рд░рд╛ рдбреНрд░рд╛рдЗрд╡рд░ PG рд╣реИред
рдХрдХреНрд╖рд╛ рд╕реЗ рд╣рдореЗрдВ рддреАрди рдЪреАрдЬреЗрдВ рдЪрд╛рд╣рд┐рдП:
- рдХрд░реНрд╕рд░ рдХреЛ рдЦреЛрд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛред
- рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛред
- рдХрд░реНрд╕рд░ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛред
рдХрд░реНрд╕рд░ рдЦреЛрд▓реЗрдВ:
public function openCursor() { if ($this->connection->getTransactionNestingLevel() === 0) { throw new \BadMethodCallException('Cursor must be used inside a transaction'); } $query = clone $this->query; $query->setSQL(sprintf( 'DECLARE %s CURSOR FOR (%s)', $this->connection->quoteIdentifier($this->cursorName), $this->query->getSQL() )); $query->execute($this->query->getParameters()); $this->isOpen = true; }
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛, рдПрдХ рд▓реЗрди-рджреЗрди рдореЗрдВ рдЕрднрд┐рд╢рд╛рдк рдЦреБрд▓реЗред рдЗрд╕рд▓рд┐рдП, рдпрд╣рд╛рдВ рдореИрдВ рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЦреБрд▓реЗ рд▓реЗрдирджреЗрди рдХреЗ рдЕрдВрджрд░ рдЗрд╕ рдкрджреНрдзрддрд┐ рдкрд░ рдХреЙрд▓ рдХрд░рдирд╛ рдирд╣реАрдВ рднреВрд▓ рдЧрдП рд╣реИрдВред (рднрдЧрд╡рд╛рди рдХрд╛ рд╢реБрдХреНрд░ рд╣реИ, рд╡рд╣ рд╕рдордп рдмреАрдд рдЪреБрдХрд╛ рд╣реИ рдЬрдм рдореБрдЭреЗ рдпрд╣реАрдВ рд▓реЗрди-рджреЗрди рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛!)
рдПрдХ рдирдпрд╛ NativeQuery рдмрдирд╛рдиреЗ рдФрд░ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдмрд╕ рдПрдХ рдХреЛ рдХреНрд▓реЛрди рдХрд░рддрд╛ рд╣реВрдВ рдЬрд┐рд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЦрд┐рд▓рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕реЗ DECLARE ... CURSOR FOR (here_original_query) рдореЗрдВ рд▓рдкреЗрдЯреЗрдВред рдореИрдВ рдЗрд╕реЗ рдмрд╛рд╣рд░ рд▓реЗ рдЬрд╛рддрд╛ рд╣реВрдВред
рдЪрд▓реЛ getFetchQuery рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВред рдпрд╣ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд▓реМрдЯрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдЕрдиреНрдп рдЕрдиреБрд░реЛрдз рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ рдХрд┐ рджрд┐рдП рдЧрдП рдмреИрдЪреЛрдВ рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИред рдЗрд╕рд╕реЗ рдХреЙрд▓рд┐рдВрдЧ рдХреЛрдб рдХреЛ рдЕрдзрд┐рдХ рд╕реНрд╡рддрдВрддреНрд░рддрд╛ рдорд┐рд▓рддреА рд╣реИред
public function getFetchQuery(int $count = 1): NativeQuery { $query = clone $this->query; $query->setParameters([]); $query->setSQL(sprintf( 'FETCH FORWARD %d FROM %s', $count, $this->connection->quoteIdentifier($this->cursorName) )); return $query; }
рд╡рд┐рдзрд┐ рдХрд╛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ - рдпрд╣ рдмрдВрдбрд▓ рдХрд╛ рдЖрдХрд╛рд░ рд╣реИ, рдЬреЛ рдЗрд╕ рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рд╡рд╛рдкрд╕ рдХрд┐рдП рдЧрдП рдЕрдиреБрд░реЛрдз рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдмрди рдЬрд╛рдПрдЧрд╛ред рдореИрдВ рдХреНрд╡реЗрд░реА рдХреНрд▓реЛрдирд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдЪрд╛рд▓ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЕрдзрд┐рд▓реЗрдЦрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ SQL рдХреЛ FETCH ... FROM ..., рдирд┐рд░реНрдорд╛рдг рдХреЗ рд╕рд╛рде рдмрджрд▓ рджреЗрддрд╛ рд╣реВрдВред
GetFetchQuery () рдХреЛ рдЕрдЪрд╛рдирдХ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХрд░реНрд╕рд░ рдХреЛ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛ (рдЕрдЪрд╛рдирдХ рдореБрдЭреЗ рдкрд░реНрдпрд╛рдкреНрдд рдиреАрдВрдж рдирд╣реАрдВ рдорд┐рд▓реЗрдЧреА), рдореИрдВ рд╕реАрдзреЗ getFetchQuery () рд╡рд┐рдзрд┐ рдореЗрдВ рдЗрд╕рдХрд╛ рдПрдХ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЙрджреНрдШрд╛рдЯрди рдХрд░реВрдВрдЧрд╛:
public function getFetchQuery(int $count = 1): NativeQuery { if (!$this->isOpen) { $this->openCursor(); } тАж
рдФрд░ OpenCursor () рдкрджреНрдзрддрд┐ рдХреЛ рд╣реА рдирд┐рдЬреА рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЬрдм рдореБрдЭреЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ, рдореИрдВ рдЙрди рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЛ рдирд╣реАрдВ рджреЗрдЦреВрдВрдЧрд╛ред
GetFetchQuery () рдХреЗ рдЕрдВрджрд░, рдореИрдВ рдХрд░реНрд╕рд░ рдХреЛ рдЖрдЧреЗ рд▓реЗ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рд╛рд░реНрдб-рдХреЛрдбреЗрдб рдлреЙрд░рд╡рд░реНрдб рдХреЛ рджреА рдЧрдИ рд▓рд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рддрд╛ рд╣реВрдВред рд▓реЗрдХрд┐рди FETCH рдХреЙрд▓рд┐рдВрдЧ рдореЛрдб рдХрдИ рдЕрд▓рдЧ рд╣реИрдВред рдЪрд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рднреА рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ?
const DIRECTION_NEXT = 'NEXT'; const DIRECTION_PRIOR = 'PRIOR'; const DIRECTION_FIRST = 'FIRST'; const DIRECTION_LAST = 'LAST'; const DIRECTION_ABSOLUTE = 'ABSOLUTE';
рдЙрдирдореЗрдВ рд╕реЗ рдЖрдзреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рд▓рд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЕрдиреНрдп рдЖрдзреЗ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдореБрдЭреЗ рдХреНрдпрд╛ рдорд┐рд▓рд╛ рд╣реИ:
public function getFetchQuery(int $count = 1, string $direction = self::DIRECTION_FORWARD): NativeQuery { if (!$this->isOpen) { $this->openCursor(); } $query = clone $this->query; $query->setParameters([]); if ( $direction == self::DIRECTION_ABSOLUTE || $direction == self::DIRECTION_RELATIVE || $direction == self::DIRECTION_FORWARD || $direction == self::DIRECTION_BACKWARD ) { $query->setSQL(sprintf( 'FETCH %s %d FROM %s', $direction, $count, $this->connection->quoteIdentifier($this->cursorName) )); } else { $query->setSQL(sprintf( 'FETCH %s FROM %s', $direction, $this->connection->quoteIdentifier($this->cursorName) )); } return $query; }
CLOSE рдХреЗ рд╕рд╛рде рдХрд░реНрд╕рд░ рдХреЛ рдмрдВрдж рдХрд░реЗрдВ, рд▓реЗрди-рджреЗрди рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ:
public function close() { if (!$this->isOpen) { return; } $this->connection->exec('CLOSE ' . $this->connection->quoteIdentifier($this->cursorName)); $this->isOpen = false; }
рдирд╛рд╢рдХ:
public function __destruct() { if ($this->isOpen) { $this->close(); } }
рдпрд╣рд╛рдБ рд╕рдореНрдкреВрд░реНрдг рд╡рд░реНрдЧ рдЕрдкрдиреА рд╕рдВрдкреВрд░реНрдгрддрд╛ рдореЗрдВ рд╣реИ ред рдЪрд▓реЛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ?
рдореИрдВ рдХреБрдЫ рд╕рд╢рд░реНрдд XLSX рдореЗрдВ рдХреБрдЫ рд╕рд╢рд░реНрдд рд▓реЗрдЦрдХ рдЦреЛрд▓рддрд╛ рд╣реВрдВред
$writer->openToFile($targetFile);
рдпрд╣рд╛рдВ рдореБрдЭреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдСрд░реНрдбрд░ рдХреА рд╕реВрдЪреА рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП NativeQuery рдорд┐рд▓рддрд╛ рд╣реИред
$query = $this->getOrdersRepository($em) ->getOrdersFiltered($dateFrom, $dateTo, $filters);
рдЗрд╕ рдХреНрд╡реЗрд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдореИрдВ рдПрдХ рдХрд░реНрд╕рд░ рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реВрдВред
$cursor = new PgSqlNativeQueryCursor($query);
рдФрд░ рдЙрд╕рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ 10,000 рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рдмреИрдЪреЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рдорд┐рд▓рддрд╛ рд╣реИред
$fetchQuery = $cursor->getFetchQuery(10000);
рдЬрдм рддрдХ рдореБрдЭреЗ рдХреЛрдИ рдЦрд╛рд▓реА рдкрд░рд┐рдгрд╛рдо рдирд╣реАрдВ рдорд┐рд▓ рдЬрд╛рддрд╛, рдореИрдВ рдЗрд╕рдХрд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддрд╛ рд╣реВрдВ рдкреНрд░рддреНрдпреЗрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдореЗрдВ, рдореИрдВ FETCH рдХрд░рддрд╛ рд╣реВрдВ, рдкрд░рд┐рдгрд╛рдо рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдПрдХ рдлрд╛рдЗрд▓ рдкрд░ рд▓рд┐рдЦрддрд╛ рд╣реВрдВред
do { $result = $fetchQuery->getArrayResult(); foreach ($result as $row) { $writer->addRow($this->toXlsxRow($row)); } } while ($result);
рдореИрдВ рдХрд░реНрд╕рд░ рдФрд░ рд▓реЗрдЦрдХ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реВрдВред
$cursor->close(); $writer->close();
рдореИрдВ рдЕрд╕реНрдерд╛рдпреА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдбрд┐рд╕реНрдХ рдкрд░ рдлрд╝рд╛рдЗрд▓ рд▓рд┐рдЦрддрд╛ рд╣реВрдВ, рдФрд░ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдкреВрд░реА рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдореИрдВ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рднреЗрдЬ рджреЗрддрд╛ рд╣реВрдВ, рд╕реНрдореГрддрд┐ рдореЗрдВ рдмрдлрд░рд┐рдВрдЧ рдХрд░рддрд╛ рд╣реВрдВред
рдкрдврд╝реЗрдВ READY! рд╣рдордиреЗ рд╕рднреА рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП PHP рд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдФрд░ рднрд╛рд░реА рдкреНрд░рд╢реНрдиреЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд╕рд╛рде рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдпрд╛рддрдирд╛ рдирд╣реАрдВ рджреАред рдФрд░ рдЕрдирд▓реЛрдбрд┐рдВрдЧ рдиреЗ рдЕрдиреБрд░реЛрдз рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдЖрдзрд╛рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рд╕рдордп рд▓рд┐рдпрд╛ред
рджреЗрдЦреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрдкрдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдРрд╕реЗ рд╕реНрдерд╛рди рд╣реИрдВ рдЬреЛ рдХрд░реНрд╕рд░ рдХреЗ рд╕рд╛рде рдореЗрдореЛрд░реА рдХреЛ рдЧрддрд┐ / рд╕рд╣реЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ?