Мен сизге Владимир Ситниковдун 2016-жылдын башында "PostgreSQL жана JDBC ширенин баарын сыгып жатышат" баяндамасынын стенограммасын окууну сунуштайм.


Кутмандуу күнүң менен! Менин атым Владимир Ситников. Мен NetCracker компаниясында 10 жылдан бери иштейм. Анан мен көбүнчө өндүрүмдүүлүккө жакынмын. Java менен байланышкандын баары, SQL менен байланышкандын баары мен жакшы көрөм.
Бүгүн мен PostgreSQLди маалымат базасы сервери катары колдоно баштаганда компанияда эмнеге туш болгонубуз жөнүндө сүйлөшөм. Жана биз көбүнчө Java менен иштейбиз. Бирок бүгүн айта турган нерсем Java жөнүндө гана эмес. Практика көрсөткөндөй, бул башка тилдерде да кездешет.

Биз сүйлөшөбүз:
- маалыматтарды тандоо жөнүндө.
- Дайындарды сактоо жөнүндө.
- Ошондой эле аткаруу жөнүндө.
- Ал эми ошол жерде көмүлгөн суу астындагы тырмоолор жөнүндө.

Жөнөкөй суроо менен баштайлы. Негизги ачкычтын негизинде таблицадан бир катар тандайбыз.

Маалымат базасы ошол эле хостто жайгашкан. Ал эми бул чарбачылыктын бардыгы 20 миллисекундду талап кылат.

Бул 20 миллисекунд көп. Эгер сизде 100 ушундай өтүнүч болсо, анда сиз секундасына бул суроо-талаптарды сыдырууга убакыт коротасыз, б.а. биз убакытты текке кетирип жатабыз.
Биз муну жактырбайбыз жана бул үчүн база бизге эмне сунуштап жатканын карап көрөлү. Маалыматтар базасы бизге суроо-талаптарды аткаруунун эки вариантын сунуштайт.

Биринчи параметр жөнөкөй өтүнүч болуп саналат. Мунун эмнеси жакшы? Алып жибергенибиз, андан башка эч нерсе эмес.

Маалымат базасында дагы татаал, бирок функционалдуураак болгон өркүндөтүлгөн суроо бар. Сиз өзүнчө талдоо, аткаруу, өзгөрүлмө байлоо ж.б. үчүн суроо-талапты жөнөтө аласыз.
Супер кеңейтилген суроо - бул биз учурдагы отчетто камтылбай турган нерсе. Биз, балким, маалымат базасынан бир нерсени каалайбыз жана кандайдыр бир формада түзүлгөн каалоолордун тизмеси бар, б.а. бул биз каалаган нерсе, бирок азыр жана кийинки жылы бул мүмкүн эмес. Ошентип, биз аны жөн эле жаздык жана биз негизги адамдарды титиреп айланабыз.

Жана биз кыла турган нерсе - жөнөкөй суроо жана кеңейтилген суроо.
Ар бир ыкманын өзгөчөлүгү эмнеде?
Жөнөкөй суроо бир жолку аткаруу үчүн жакшы. Бир жолу жасалып, унутулуп калган. Ал эми маселе, ал экилик маалымат форматын колдобойт, башкача айтканда, кээ бир жогорку өндүрүмдүү системалар үчүн ылайыктуу эмес.

Кеңейтилген суроо – талдоо үчүн убакытты үнөмдөөгө мүмкүндүк берет. Бул биз жасап, колдоно баштадык. Бул бизге чындап жардам берди. талдоо боюнча үнөмдөө гана эмес. Маалыматтарды өткөрүүдө үнөмдөө бар. Маалыматтарды экилик форматта өткөрүү алда канча натыйжалуу.

Келгиле, практикага өтөлү. Кадимки колдонмо ушундай көрүнөт. Бул Java ж.б. болушу мүмкүн.
Биз билдирүү түздүк. Буйрукту аткарды. Жакын түзүлгөн. Бул жерде ката кайда? Көйгөй эмнеде? Көйгөй жок. Бул бардык китептерде айтылат. Мына ушундай жазылышы керек. Эгер сиз максималдуу аткарууну кааласаңыз, ушинтип жазыңыз.

Бирок бул иштебей турганын практика көрсөттү. Неге? Анткени бизде “жакын” ыкма бар. Жана биз муну кылганда, маалымат базасы көз карашынан алганда, бул маалымат базасы менен иштеген тамеки чеккенге окшош экен. Биз "PARSE EXECUTE DEALLOCATE" дедик.
Эмне үчүн мындай кошумча түзүү жана билдирүүлөрдү түшүрүү? Алардын эч кимге кереги жок. Бирок, адатта, PreparedStatements'те эмне болот, биз аларды жапканыбызда, алар маалымат базасындагы бардыгын жабышат. Бул биз каалаган нерсе эмес.

Биз дени сак адамдардай эле база менен иштешүүнү каалайбыз. Арызды бир жолу алып, даярдап, анан көп жолу аткардык. Чынында, көп жолу - бул тиркемелердин жашоосунда бир жолу - алар талданган. Жана биз бир эле билдирүү идентификаторун ар кандай RESTтерде колдонобуз. Бул биздин максатыбыз.

бул кантип жетсек болот?

Бул абдан жөнөкөй - билдирүүлөрдү жабуунун кереги жок. Биз муну мындайча жазабыз: "даярдоо" "аткаруу".


Эгерде биз ушул сыяктуу бир нерсени ишке киргизсек, анда бир нерсе бир жерден ашып түшөрү анык. Эгерде ал түшүнүксүз болсо, анда аракет кылып көрүңүз. Бул жөнөкөй ыкманы колдонгон эталон жазалы. Билдирүүнү түзүү. Биз аны драйвердин кандайдыр бир версиясында ишке киргизип, анын эс тутумун жоготуу менен тез эле бузулуп жатканын байкайбыз.
Мындай каталар оңой эле оңдолот экени түшүнүктүү. Мен алар жөнүндө айтпай эле коёюн. Бирок мен айта кетейин, жаңы версия бир топ ылдам иштейт. Метод акылсыз, бирок дагы эле.

Кантип туура иштөө керек? Бул үчүн биз эмне кылышыбыз керек?
Чындыгында, колдонмолор ар дайым билдирүүлөрдү жабышат. Бардык китептерде жаба бергиле, антпесе эс-тутум агып кетет дешет.
Жана PostgreSQL сурамдарды кантип кэш кылууну билбейт. Ар бир сеанс өзү үчүн бул кэш түзүшү керек.
Жана биз да талдоо үчүн убакытты короткубуз келбейт.

Ал эми бизде адаттагыдай эки вариант бар.
Биринчи вариант - биз аны алып, баарын PgSQLге ороп алалы деп айтабыз. Ал жерде кэш бар. Ал баарын кэштейт. Бул сонун болуп калат. Биз муну көрдүк. Бизде 100500 өтүнүч бар. Иштебейт. Биз өтүнүчтөрдү кол менен процедурага айландырууга макул эмеспиз. Жок жок.
Бизде экинчи вариант бар – аны алып, өзүбүз кесебиз. Биз булактарды ачып, кесип баштайбыз. Көрдүк, көрдүк. Аны жасоо анчалык деле кыйын эмес экен.

Бул 2015-жылдын август айында пайда болгон. Азыр дагы заманбап версиясы бар. Жана баары сонун. Ал ушунчалык жакшы иштегендиктен, биз колдонмодо эч нерсени өзгөртпөйбүз. Жана биз PgSQL багытында ойлонууну да токтоттук, башкача айтканда, бул бардык кошумча чыгымдарды дээрлик нөлгө чейин кыскартуу үчүн жетиштүү болду.
Демек, ар бир бир жолку суроо-талап боюнча маалымат базасында эстутумду текке кетирбөө үчүн сервер тарабынан даярдалган билдирүүлөр 5-аткарууда иштетилет.

Сиз сурасаңыз болот - сандар кайда? Эмне алып жатасың? Бул жерде мен сандарды бербейм, анткени ар бир суроонун өзүнчө суроосу бар.
Биздин сурамдар OLTP сурамдарын талдоо үчүн 20 миллисекунддай убакыт короттук. Аткаруу үчүн 0,5 миллисекунд, талдоо үчүн 20 миллисекунд болду. Сурам – 10 КБ текст, 170 сап план. Бул OLTP сурамы. Ал 1, 5, 10 саптарды, кээде андан да көптү талап кылат.
Бирок биз 20 миллисекундду текке кетиргибиз келген жок. Биз аны 0гө түшүрдүк. Баары сонун.
Бул жерден эмнени алып кете аласың? Эгер сизде Java болсо, анда сиз драйвердин заманбап версиясын алып, кубанасыз.
Эгер сиз башка тилде сүйлөсөңүз, ойлонуңуз - балким бул сизге да керекпи? Анткени акыркы тил көз карашынан алганда, мисалы, PL 8 же сизде LibPQ болсо, анда сиз аткарууга эмес, талдоо жүргүзүүгө убакыт коротуп жатканыңыз ачык эмес жана бул текшерүүгө арзыйт. Кантип? Баары бекер.

Каталар жана кээ бир өзгөчөлүктөр бар экенин эске албаганда. Жана биз азыр алар жөнүндө сүйлөшөбүз. Анын көбү өнөр жай археологиясы, биз тапкан нерселер, биз жолуккан нерселер жөнүндө болмокчу.

Эгерде суроо-талап динамикалык түрдө түзүлсө. Бул болот. Кимдир бирөө саптарды жабыштырып, натыйжада SQL сурамы пайда болот.
Эмне үчүн ал жаман? Бул жаман, анткени ар бир жолу биз ар кандай сап менен бүтөбүз.
Жана бул башка саптын hashCode кайра окуу керек. Бул чындыгында CPU тапшырмасы - атүгүл учурдагы хэштен узун суроо текстин табуу анчалык деле оңой эмес. Ошондуктан, корутунду жөнөкөй - суроо-талаптарды жаратпагыла. Аларды бир өзгөрмөдө сактаңыз. Жана кубангыла.

Кийинки маселе. Маалымат түрлөрү маанилүү. Кандай NULL бар экени маанилүү эмес, кандайдыр бир түрү болсун деген ОРМ бар. Эгерде Int болсо, анда биз setInt дейбиз. Эгерде NULL болсо, анда ал ар дайым VARCHAR болсун. Акырында NULL дегендин кандай айырмасы бар? Маалымат базасы өзү баарын түшүнөт. Жана бул сүрөт иштебейт.
Иш жүзүндө, маалымат базасы эч кандай маани бербейт. Эгер сиз биринчи жолу бул сан деп, экинчи жолу VARCHAR деп айткан болсоңуз, анда Сервер тарабынан даярдалган билдирүүлөрдү кайра колдонуу мүмкүн эмес. Ал эми мындай учурда биз билдирүүбүздү кайра түзүшүбүз керек.

Эгер сиз бир эле суроону аткарып жатсаңыз, тилкеңиздеги маалымат түрлөрү чаташтырылбаганын текшериңиз. Сиз NULL үчүн сак болушуңуз керек. Бул биз PreparedStatements колдоно баштагандан кийин болгон жалпы ката

Макул, күйгүзүлдү. Балким алар айдоочуну алып кетишкендир. Жана өндүрүмдүүлүк төмөндөдү. Жаман болуп кетти.
Бул кантип болот? Бул ката же өзгөчөлүкбү? Тилекке каршы, бул ката же өзгөчөлүк экенин түшүнүү мүмкүн болгон жок. Бирок бул көйгөйдү кайра чыгаруунун өтө жөнөкөй сценарийи бар. Ал күтүүсүздөн бизди буктурмага алды. Жана ал түзмө-түз бир таблицадан үлгү алуудан турат. Бизде, албетте, мындай өтүнүчтөр көбүрөөк болду. Эреже катары, алар эки же үч үстөлдү камтыган, бирок мындай ойнотуу сценарийи бар. Базаңыздан каалаган версиясын алып, ойноңуз.

Кеп бизде эки тилке бар, алардын ар бири индекстелген. Бир NULL тилкеде миллион саптар бар. Ал эми экинчи тилкеде 20 гана сап бар. Чектелген өзгөрмөлөрсүз аткарганда, баары жакшы иштейт.
Эгерде биз чектелген өзгөрмөлөр менен аткара баштасак, б.а., биз "?" же "$1" биздин суроо-талап үчүн, биз эмнени алабыз?

Биринчи аткаруу күтүлгөндөй эле. Экинчиси бир аз ылдамыраак. Бир нерсе кэштелген. Үчүнчү, төртүнчү, бешинчи. Андан кийин жарылуу - жана ушул сыяктуу бир нерсе. Эң жаманы, бул алтынчы өлүм жазасына тартылганда болот. Чыныгы аткаруу планы эмне экенин түшүнүү үчүн так алты өлүмдү аткаруу зарыл экенин ким билет?

Ким күнөөлүү? Эмне болду? Маалыматтар базасы оптималдаштырууну камтыйт. Жана бул жалпы иш үчүн оптималдаштырылган окшойт. Жана, ошого жараша, кандайдыр бир учурдан баштап, ал жалпы планга өтөт, тилекке каршы, башкача болушу мүмкүн. Ошол эле болуп чыгышы мүмкүн, же башкача болушу мүмкүн. Жана бул жүрүм-турумга алып келе турган кандайдыр бир чектик маани бар.
Бул тууралуу эмне кыла аласыз? Бул жерде, албетте, бир нерсени болжолдоо кыйыныраак. Биз колдонгон жөнөкөй чечим бар. Бул +0, OFFSET 0. Сиз мындай чечимдерди билесиз. Биз жөн гана алып, суроо-талапка "+0" кошобуз жана баары жакшы. Мен сага кийинчерээк көрсөтөм.
Жана дагы бир вариант бар - пландарды кылдаттык менен караңыз. Иштеп чыгуучу бир гана суроо-талап жазып тим болбостон, 6 жолу “талдоону түшүндүрүп бер” деп айтышы керек. 5 болсо, иштебейт.
Ал эми үчүнчү вариант бар - pgsql-хакерлерге кат жаз. Мен жаздым, бирок бул ката же өзгөчөлүкбү азырынча белгисиз.

Бул мүчүлүштүктөрбү же өзгөчөлүкбү деп ойлонуп жатып, аны оңдойлу. Өтүнүчүбүздү алып, “+0” кошолу. Баары жакшы. Эки белгилер жана ал кандайча же бул эмне жөнүндө ойлонуунун да кереги жок. Өтө жөнөкөй. Биз жөн гана маалымат базасына бул тилкеде индексти колдонууга тыюу салдык. Бизде "+0" тилкесинде индекс жок жана бүттү, маалымат базасы индексти колдонбойт, баары жакшы.

Бул 6 эрежени түшүндүрөт. Эми учурдагы версияларда, эгер сизде чектелген өзгөрмөлөр болсо, аны 6 жолу жасашыңыз керек. Эгер сизде чектелген өзгөрмөлөр жок болсо, биз муну жасайбыз. Акырында дал ушул өтүнүч ишке ашпай калат. Бул татаал нерсе эмес.
Көрсө, бул канчалык мүмкүн? Бул жерде ката, бул жерде ката. Чынында, мүчүлүштүк бардык жерде бар.

Келгиле, жакыныраак карап көрөлү. Мисалы, бизде эки схема бар. А схемасы S таблицасы жана В диаграммасы S таблицасы. Сурам – таблицадан маалыматтарды тандоо. Бул учурда бизде эмне болот? Бизде ката болот. Бизде жогоруда айтылгандардын баары болот. Эреже - ката бардык жерде, бизде жогоруда айтылгандардын баары болот.

Эми суроо: "Эмне үчүн?" Эгерде бизде схема бар болсо, анда таблицаны кайдан издөө керектигин айткан "search_path" өзгөрмөсү бар деген документтер бар окшойт. Бул өзгөрмө бар окшойт.
Көйгөй эмнеде? Көйгөй сервер тарабынан даярдалган билдирүүлөр search_path кимдир бирөө тарабынан өзгөртүлүшү мүмкүн деп шектенбейт. Бул маани маалымат базасы үчүн туруктуу бойдон кала берет. Ал эми кээ бир бөлүктөрү жаңы маанилерди албай калышы мүмкүн.

Албетте, бул сиз сынап жаткан версияга жараша болот. Сиздин үстөлдөргө канчалык олуттуу түрдө айырмаланганына жараша болот. Ал эми 9.1 версиясы жөн гана эски сурамдарды аткарат. Жаңы версиялар катаны кармап, сизде ката бар экенин айтышы мүмкүн.

Кантип дарылоо керек? Жөнөкөй рецепт бар - аны кылбаңыз. Колдонмо иштеп жатканда search_path өзгөртүүнүн кереги жок. Эгер сиз өзгөрсөңүз, анда жаңы байланыш түзүү жакшы.
Сиз талкуулай аласыз, б.а. ачуу, талкуулоо, кошуу. Мүмкүн, биз маалымат базасын иштеп чыгуучуларды кимдир бирөө маанини өзгөрткөндө, маалымат базасы кардарга бул тууралуу айтып бериши керек деп ишендире алабыз: “Мына, бул жерде сиздин баалуулугуңуз жаңыртылган. Балким, сиз билдирүүлөрдү баштапкы абалга келтирип, кайра түзүшүңүз керекпи?» Азыр маалымат базасы өзүн жашыруун алып барат жана эч кандай билдирүүлөр ичинде кандайдыр бир жерде өзгөрдү деп билдирбейт.
Мен дагы бир жолу баса белгилейм - бул Java үчүн мүнөздүү эмес нерсе. Биз PL/pgSQLде бир эле нерсени көрөбүз. Бирок ошол жерде кайра чыгарылат.

Келгиле, дагы бир аз маалымат тандоого аракет кылалы. Биз тандайбыз жана тандайбыз. Бизде миллион саптан турган үстөл бар. Ар бир сап бир килобайт. Болжол менен бир гигабайт маалымат. Ал эми бизде Java машинасында 128 мегабайт жумушчу эс тутум бар.
Биз, бардык китептерде сунушталгандай, агымдык процессингди колдонобуз. Башкача айтканда, биз resultSetти ачып, ал жерден аз-аздан маалыматтарды окуйбуз. Иштейби? Эстен түшпөйбү? Бир аз окуйсузбу? Келгиле, маалымат базасына ишенели, Постгреске ишенели. Биз ишенбейбиз. Биз OutOFMemory кулап калабызбы? OutOfMemory менен кимдер башынан өттү? Ошондон кийин аны ким оңдой алды? Кимдир бирөө аны оңдоого жетишти.
Эгерде сизде миллион саптар болсо, анда сиз жөн гана тандап, тандай албайсыз. OFFSET/LIMIT талап кылынат. Бул вариант үчүн ким? Ал эми autoCommit менен ойноону ким колдойт?
Бул жерде, адаттагыдай эле, эң күтүүсүз вариант туура болуп чыгат. Жана күтүлбөгөн жерден autoCommitти өчүрсөңүз, бул жардам берет. Эмнеге андай? Бул тууралуу илим билбейт.

Бирок, демейки боюнча, Postgres маалымат базасына туташкан бардык кардарлар бардык маалыматтарды алып келишет. PgJDBC бул жагынан өзгөчө эмес, ал бардык саптарды тандайт.
FetchSize темасында вариация бар, башкача айтканда, сиз өзүнчө билдирүү деңгээлинде айта аласыз, бул жерде, сураныч, 10, 50 боюнча маалыматтарды тандаңыз. Бирок бул autoCommit өчүрүлмөйүнчө иштебейт. AutoCommit өчүрүлгөн - ал иштей баштайт.
Бирок коддон өтүп, бардык жерде setFetchSize орнотуу ыңгайсыз. Ошондуктан, биз бүт байланыш үчүн демейки маанини айта турган жөндөө жасадык.

Биз ошону айттык. Параметр конфигурацияланды. Анан эмне алдык? Эгерде биз кичинекей суммаларды тандасак, мисалы, бир эле учурда 10 катарды тандасак, анда бизде өтө чоң кошумча чыгымдар болот. Ошондуктан, бул көрсөткүч жүзгө жакын болушу керек.

Идеалында, албетте, сиз дагы эле аны байт менен чектөөнү үйрөнүшүңүз керек, бирок рецепт бул: defaultRowFetchSizeди жүздөн ашык кылып коюңуз жана бактылуу болуңуз.

Келгиле, маалыматтарды киргизүүнү уланталы. Кыстаруу оңой, ар кандай варианттар бар. Мисалы, INSERT, VALUES. Бул жакшы вариант. Сиз "INSERT SELECT" деп айта аласыз. Практикада дал ушундай. аткарууда эч кандай айырма жок.
Китептерде Пакеттик билдирүүнү аткаруу керек деп айтылат, китептерде бир нече кашаа менен татаалыраак буйруктарды аткарууга болот деп айтылат. Ал эми Postgresтин сонун өзгөчөлүгү бар - сиз COPY кыла аласыз, б.а. муну тезирээк жасай аласыз.

Аны өлчөп көрсөңүз, кайрадан кызыктуу ачылыштарды жасай аласыз. Мунун кандай иштешин каалайбыз? Биз талдоо жана керексиз буйруктарды аткарбоо үчүн келет.

Иш жүзүндө, TCP бизге муну кылууга жол бербейт. Эгерде кардар суроо-талап жөнөтүү менен алек болсо, анда маалымат базасы бизге жооп жөнөтүү аракетинде суроо-талаптарды окубайт. Түмүккэ тыа хаһаайыстыбатын үтүөлээх үлэһитэ, тыа хаһаайыстыбатын үтүөлээх үлэһитэ.

Ошентип, кардар мезгил-мезгили менен синхрондоштуруу пакетин жөнөтүүгө аргасыз болот. Кошумча тармактык өз ара аракеттенүү, кошумча убакытты текке кетирүү.
Жана аларды канчалык көп кошсок, ошончолук начарлайт. Айдоочу абдан пессимист жана аларды бат-баттан, болжол менен 200 сапка бир жолу кошуп, сызыктардын өлчөмүнө жараша ж.б.

Бир эле сапты оңдосоңуз, баары 10 эсе ылдамдайт. Бул болот. Неге? Адаттагыдай эле, буга чейин бир жерде ушундай туруктуу колдонулган. Ал эми "128" мааниси партиялоону колдонбоону билдирген.

Бул расмий версияга кирбей калганы жакшы. Чыгаруу башталганга чейин табылган. Мен берген маанилердин баары заманбап варианттарга негизделген.

Келиңиз, аны кийип көрөлү. Биз InsertBatch жөнөкөй өлчөө. InsertBatch бир нече жолу өлчөйбүз, б.а. бир эле нерсе, бирок көп баалуулуктар бар. Татаал кыймыл. Муну баары эле жасай албайт, бирок бул COPYге караганда жөнөкөй кадам.

COPY кыла аласыз.

Жана сиз муну структураларда жасай аласыз. Колдонуучунун демейки түрүн жарыялаңыз, массивди өткөрүңүз жана түз таблицага INSERT.
Эгер сиз шилтемени ачсаңыз: pgjdbc/ubenchmsrk/InsertBatch.java, анда бул код GitHub'та. Сиз ошол жерде кандай суроо-талаптар түзүлүп жатканын көрө аласыз. Маанилүү эмес.

Биз ишке киргиздик. Жана биз түшүнгөн биринчи нерсе, партияны колдонбоо жөн эле мүмкүн эмес. Бардык пакеттөө опциялары нөлгө барабар, башкача айтканда, аткаруу убактысы бир жолку аткарууга салыштырмалуу дээрлик нөлгө барабар.

Биз маалыматтарды киргизебиз. Бул абдан жөнөкөй стол. Үч мамыча. Жана биз бул жерде эмнени көрүп жатабыз? Биз бул үч варианттын тең болжолдуу түрдө салыштырууга болоорун көрөбүз. Жана COPY, албетте, жакшыраак.

Бул бөлүктөрүн киргизгенибизде. Бир VALUES мааниси, эки VALUES мааниси, үч VALUES мааниси деп айтканда, же алардын 10ун үтүр менен бөлүп көрсөттүк. Бул азыр горизонталдуу. 1, 2, 4, 128. Көгүлтүр түс менен тартылган Пакеттик Кыстарма анын өзүн бир топ жакшыртканын көрүүгө болот. Башкача айтканда, сиз бирден киргизгениңизде, жада калса төртөөнү бирден киргизгениңизде, ал эки эсе жакшы болуп калат, анткени биз БААЛУУГА бир аз көбүрөөк тыгылганбыз. АТКАРЫЛУУ операциялары азыраак.
Кичинекей көлөмдө COPY колдонуу өтө келечексиз. Алгачкы экөөнү да тарткан жокмун. Алар асманга, башкача айтканда, КӨЧҮРҮҮ үчүн бул жашыл сандар.
COPY сизде жок дегенде жүз катар маалыматтар болгондо колдонулушу керек. Бул байланышты ачууга кеткен чыгым чоң. Чынын айтсам, мен бул багытта казган жокмун. Мен партияны оптималдаштырдым, бирок КӨЧҮРҮҮ эмес.
Андан ары эмне кылабыз? Биз аракет кылып көрдүк. Биз же структураларды же бир нече маанилерди айкалыштырган акылдуу бактны колдонуу керек экенин түшүнөбүз.

Бүгүнкү баяндамадан эмнени алып салуу керек?
- PreparedStatement биздин бардыгыбыз. Бул өндүрүмдүүлүк үчүн көп берет. Бул майдын ичинде чоң флоп чыгарат.
- Ал эми 6 жолу ТҮШҮНДҮРҮШҮҢҮЗ керек.
- Ал эми көйгөйлүү суроолорубуздун калган пайызын оңдоо үчүн OFFSET 0 жана +0 сыяктуу трюктарды суюлушубуз керек.
Source: www.habr.com
