PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Докладда мүмкүнчүлүк берген айрым ыкмалар келтирилген күнүнө миллиондогон болгондо SQL сурамдарынын аткарылышын көзөмөлдөө, жана жүздөгөн көзөмөлдөнгөн PostgreSQL серверлери бар.

Кандай техникалык чечимдер бизге мындай көлөмдөгү маалыматты эффективдүү иштетүүгө мүмкүндүк берет жана бул жөнөкөй иштеп чыгуучунун жашоосун кантип жеңилдетет?


Ким кызыкдар? конкреттүү көйгөйлөрдү жана ар кандай оптималдаштыруу ыкмаларын талдоо SQL сурамдары жана PostgreSQLдеги типтүү DBA көйгөйлөрүн чечүү - сиз да жасай аласыз бир катар макалаларды оку Бул тема боюнча.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)
Менин атым Кирилл Боровиков, мен өкүлүм Тензор компаниясы. Тактап айтканда, мен биздин компанияда маалымат базалары менен иштөө боюнча адистешкен.

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

Жалпысынан алганда, биздин миллион кардарлар үчүн Tensor болуп саналат VLSI биздин колдонмо болуп саналат: корпоративдик социалдык тармак, видеобайланыш үчүн чечимдер, ички жана тышкы документ жүгүртүү үчүн, бухгалтердик эсеп жана кампалар үчүн эсептик системалар,... Башкача айтканда, бизнести комплекстүү башкаруу үчүн мындай “мега-комбинат”, анда 100дөн ашык ар түрдүү ички долбоорлор.

Алардын бардыгы нормалдуу иштеп, өнүгүүсүн камсыз кылуу үчүн бизде өлкө боюнча 10 өнүктүрүү борборлору бар, аларда дагы көп 1000 иштеп чыгуучулар.

Биз PostgreSQL менен 2008-жылдан бери иштеп келе жатабыз жана биз иштеп жаткан нерселердин чоң көлөмүн топтодук - кардар маалыматтары, статистикалык, аналитикалык, тышкы маалымат тутумдарынын маалыматтары - 400TB ашык. Өндүрүштө эле 250дөй сервер бар, жалпысынан биз көзөмөлдөгөн 1000ге жакын маалымат базасы серверлери бар.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

SQL – декларативдик тил. Сиз бир нерсе "кантип" иштеши керек экенин эмес, "эмнеге" жетүүнү каалап жатканыңызды сүрөттөөсүз. DBMS JOINди кантип жасоону жакшы билет - таблицаларыңызды кантип туташтыруу керек, кандай шарттарды коюу керек, индекстен эмне өтөт, эмне болбойт...

Кээ бир DBMSs кеңештерди кабыл алат: "Жок, бул эки таблицаны баланча кезекте туташтырыңыз", бирок PostgreSQL муну кыла албайт. Бул алдыңкы иштеп чыгуучулардын аң-сезимдүү позициясы: "Биз иштеп чыгуучуларга кандайдыр бир ишараттарды колдонууга уруксат бергенден көрө, суроо-талаптарды оптималдаштырууну бүтүргөнүбүз оң."

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Жалпысынан алганда, иштеп чыгуучу [DBAга] кандай классикалык көйгөйлөр менен келет? «Бул жерде биз өтүнүчтү аткардык жана бизде баары жай, баары илинип турат, бир нерсе болуп жатат... Кандайдыр бир балээ!».

Себептери дээрлик дайыма бирдей:

  • натыйжасыз суроо алгоритми
    Иштеп чыгуучу: "Азыр мен ага JOIN аркылуу SQLде 10 таблицаны берип жатам..." - жана анын шарттары керемет жолу менен эффективдүү түрдө "чечилип" жана ал баарын тез эле алат деп күтөт. Бирок кереметтер болбойт, жана мындай өзгөрүлмөлүүлүгү бар ар кандай система (бир FROMдо 10 таблица) ар дайым кандайдыр бир каталарды берет. [макала]
  • тиешеси жок статистика
    Бул пункт PostgreSQL үчүн өзгөчө актуалдуу, сиз серверге чоң маалымат топтомун "төктөгөндө", суроо-талап кылганыңызда, ал планшетиңизди "сексканит кылат". Анткени кечээ анда 10 жазуу бар болчу, бүгүн 10 миллион, бирок PostgreSQL бул тууралуу азырынча биле элек, биз бул тууралуу айтып беришибиз керек. [макала]
  • ресурстарга "кошуу"
    Сиз диск, эстутум же процессордун иштеши жетишсиз алсыз серверге чоң жана катуу жүктөлгөн маалымат базасын орноттуңуз. Мына ошонун баары... Бир жерде сиз мындан ары секире албай турган аткаруу шыпы бар.
  • бөгөт коюу
    Бул татаал пункт, бирок алар ар кандай өзгөртүү сурамдары үчүн эң актуалдуу (INSERT, UPDATE, DELETE) - бул өзүнчө чоң тема.

План алуу

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

PostgreSQL үчүн суроо-талаптарды аткаруу планы - бул текстти көрсөтүүдө суроону аткаруу алгоритминин дарагы. Пландоочунун анализинин натыйжасында так алгоритм эң эффективдүү деп табылган.

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

Сурам планын алуу үчүн, эң оңой жолу - билдирүүнү аткаруу EXPLAIN. Бардык чыныгы атрибуттарды алуу үчүн, башкача айтканда, негизи боюнча суроо-талапты иш жүзүндө аткаруу үчүн - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

Жаман жагы: сиз аны иштеткенде, ал "бул жерде жана азыр" болот, андыктан ал жергиликтүү мүчүлүштүктөрдү оңдоо үчүн гана ылайыктуу. Эгер сиз маалымат алмашуунун күчтүү агымы астында турган өтө жүктөлгөн серверди алсаңыз, анда: “О! Бул жерде биз жай аткарылып жатабызXia өтүнүч." Жарым саат, бир саат мурун - сиз иштеп жатканыңызда жана журналдардан бул сурамды алып, серверге кайра алып келгенде, сиздин бүт маалымат топтомуңуз жана статистикаңыз өзгөрдү. Мүчүлүштүктөрдү оңдоо үчүн сиз аны иштетесиз - жана ал тез иштейт! Анан эмне үчүн, эмне үчүн түшүнө албайсың ал жай.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Сурам серверде аткарылган учурда эмне болгонун түшүнүү үчүн акылдуу адамдар жазышкан auto_explain модулу. Ал дээрлик бардык кеңири таралган PostgreSQL бөлүштүрүүдө бар жана жөн гана конфигурация файлында активдештирүү мүмкүн.

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

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

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

Бирок бул ачык-айкын болбосо да, ыңгайсыз болсо дагы, дагы негизги көйгөйлөр бар:

  • Түйүн көрсөтөт бүт ички дарактын ресурстарынын суммасы анын астында. Башкача айтканда, сиз бул конкреттүү Индекс сканерлөөсүнө канча убакыт сарпталганын биле албайсыз, эгерде анын астында кандайдыр бир уяча шарт бар болсо. Биз динамикалык түрдө "балдар" жана шарттуу өзгөрмөлөр, ичинде CTE бар же жок экенин карап чыгышыбыз керек - мунун баарын "акылыбызда" алып салуу керек.
  • Экинчи пункт: түйүндө көрсөтүлгөн убакыт жалгыз түйүн аткаруу убактысы. Эгерде бул түйүн, мисалы, бир нече жолу таблицадагы жазуулардын натыйжасында аткарылса, анда циклдердин саны — бул түйүндүн циклдери планда көбөйөт. Бирок атомдук ишке ашыруу убактысынын өзү план боюнча ошол эле бойдон калууда. Башкача айтканда, бул түйүн жалпысынан канча убакыт аткарылганын түшүнүү үчүн, бир нерсени экинчисине көбөйтүү керек - дагы бир жолу, "башыңызда".

Мындай жагдайларда "Ким эң алсыз звено?" дээрлик мүмкүн эмес. Ошондуктан, ал тургай иштеп чыгуучулар өздөрү "колдо" деп жазат "Планды түшүнүү - бул үйрөнүшү керек болгон өнөр, тажрыйба...".

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

Пландын визуализациясы

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Биз алгач "базарды аралап" чыктык - келгиле, интернеттен эмне бар экенин карап көрөлү.

Бирок аздыр-көптүр өнүгүп жаткан салыштырмалуу "тирүү" чечимдер өтө аз экени белгилүү болду - түзмө-түз бир гана: izah.depesz.com Hubert Lubaczewski тарабынан. "Түрмөк" талаасына пландын тексттик өкүлчүлүгүн киргизгениңизде, ал сизге талданган маалыматтар менен таблицаны көрсөтөт:

  • түйүндүн өзүнүн иштетүү убактысы
  • бүт ички дарак үчүн жалпы убакыт
  • статистикалык күтүлгөн алынган жазуулардын саны
  • түйүн денесинин өзү

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Бирок кичинекей көйгөйлөр да бар.

Биринчиден, көп сандагы "көчүрмө-жайлуу". Дөңгөчтүн бир бөлүгүн алып, ошол жерге жабыштырып, кайра жана кайра.

Экинчиден, окулган маалыматтардын көлөмүн талдоо жок — чыгаруучу ошол эле буферлер EXPLAIN (ANALYZE, BUFFERS), биз аны бул жерден көрбөйбүз. Ал жөн гана аларды демонтаждоону, түшүнүүнү жана алар менен иштөөнү билбейт. Көптөгөн маалыматтарды окуп жатканыңызда жана дискти жана эстутум кэшин туура эмес бөлүштүрүп жатканыңызды түшүнгөндө, бул маалымат абдан маанилүү.

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Бирок мунун баары “лирика”, биз муну менен кандайдыр бир жол менен жашай алмакпыз, бирок бизди бул кызматтан абдан алыстаткан бир нерсе бар. Бул Common Table Expression (CTE) жана InitPlan/SubPlan сыяктуу ар кандай динамикалык түйүндөрдү талдоодогу каталар.

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Ошондо биз өзүбүздүн жазуубузга убакыт келгенин түшүндүк - ураа! Ар бир иштеп чыгуучу мындай дейт: "Эми биз өзүбүз жазабыз, бул абдан жеңил болот!"

Биз веб-кызматтарга мүнөздүү стек алдык: Node.js + Express негизиндеги өзөк, кооз диаграммалар үчүн Bootstrap жана D3.js колдонулган. Жана биздин күтүүлөр толугу менен акталды - биз 2 жуманын ичинде биринчи прототибин алдык:

  • жеке план талдоочу
    Башкача айтканда, азыр биз PostgreSQL тарабынан түзүлгөн каалаган планды талдай алабыз.
  • динамикалык түйүндөрдү туура талдоо - CTE Scan, InitPlan, SubPlan
  • буферлердин бөлүштүрүлүшүн талдоо - маалымат барактары эстутумдан, локалдык кэштен, дисктен кайдан окулат
  • айкындыкка ээ болду
    Мунун баарын журналга "казып" койбой, дароо эле сүрөттө "эң алсыз шилтемени" көрүү үчүн.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Бизде синтаксисти бөлүп көрсөтүү менен ушуга окшош нерсе бар. Бирок, адатта, биздин иштеп чыгуучулар мындан ары пландын толук чагылдырылышы менен эмес, кыскараакы менен иштешет. Анткени, биз бардык сандарды талдап чыгып, аларды оңго жана солго ыргытып, ортодо биринчи сапты гана калтырдык, бул кандай түйүн: CTE Scan, CTE генерациясы же Seq Scan кандайдыр бир белги боюнча.

Бул биз чакырган кыскартылган өкүлчүлүк план шаблону.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

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

Биз түйүндү көрсөтүп, көрөбүз - Seq Scan жалпы убакыттын төрттөн биринен азын алганы, ал эми калган 3/4 бөлүгү CTE Scan тарабынан алынганы белгилүү болду. Ужас! Бул CTE Scan "оттун ылдамдыгы" жөнүндө кичинекей эскертүү, эгерде сиз аларды сурооңузда активдүү колдонсоңуз. Алар абдан тез эмес - алар кадимки стол сканерлөөдөн да төмөн. [макала] [макала]

Бирок, адатта, мындай диаграммалар кызыктуураак, татаалыраак, биз дароо сегментти көрсөтүп, мисалы, жарымынан көбү Seq Scan "жегенин" көргөндө. Анын үстүнө, ичинде кандайдыр бир Фильтр бар болчу, ага ылайык көптөгөн жазуулар жок кылынган... Бул сүрөттү түз эле иштеп чыгуучуга ыргытып: “Вася, бул жерде сен үчүн баары жаман! Түшүн, карачы – бир нерсе туура эмес болуп жатат!”

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Албетте, кээ бир "тырмоолор" катышкан.

Биринчи жолуккан нерсе тегеректөө маселеси болду. Пландагы ар бир жеке түйүндүн убактысы 1 мкс тактык менен көрсөтүлгөн. Ал эми түйүн циклдеринин саны, мисалы, 1000 ашканда - PostgreSQL аткарылгандан кийин "тактыкта" бөлүнөт, анда кайра эсептөөдө биз жалпы убакытты "0.95 жана 1.05 мс ортосунда" алабыз. Эсеп микросекунддарга жеткенде, жакшы, бирок ал [милли] секунд болгондо, ресурстарды "ким канча керектеген" планынын түйүндөрүнө "чечүүдө" бул маалыматты эске алышыңыз керек.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Экинчи жагдай, татаалыраак, динамикалык түйүндөр арасында ресурстарды (ал буферлерди) бөлүштүрүү. Бул бизге прототиптин алгачкы 2 жумасын жана дагы 4 жуманы талап кылды.

Мындай көйгөйдү чечүү оңой - биз CTE жасайбыз жана анда бир нерсени окуйбуз. Чынында, PostgreSQL "акылдуу" жана ал жерде түздөн-түз эч нерсе окубайт. Андан кийин биз андан биринчи рекордду, ага ошол эле КТЭден жүз биринчи рекордду алабыз.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Биз планды карап, түшүнөбүз - кызык, бизде Seq Scan'да 3 буфер (маалымат барактары), CTE Scan'да дагы 1 жана экинчи CTE Scan'да дагы 2 буфер бар. Башкача айтканда, бардыгын жөн эле жыйынтыктап көрсөк, биз 6 алабыз, бирок планшеттен биз 3тү гана окуйбуз! CTE Scan эч жерден эч нерсе окубайт, бирок процесстин эс тутуму менен түздөн-түз иштейт. Башкача айтканда, бул жерде бир нерсе туура эмес болуп жатат!

Чынында, бул жерде Seq Scanдан суралган 3 барак маалымат бар экен, адегенде 1-CTE Scan сураган, андан кийин 1- жана дагы 2 барак ага окулган. 2 бет эмес, 3 барак окулду.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Жана бул сүрөт бизди пландын аткарылышы мындан ары дарак эмес, жөн гана кандайдыр бир циклдик график экенин түшүнүүгө алып келди. Биз "биринчи кезекте эмнеден келгенин" түшүнүү үчүн ушундай диаграмма алдык. Башкача айтканда, бул жерде биз pg_class компаниясынан CTE түзүп, аны эки жолу сурап, 2-жолу сураганда дээрлик бардык убактыбызды филиалга жумшадык. Планшеттен 101-жазууну окууга караганда 1-жазууну окуу алда канча кымбат экени түшүнүктүү.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Биз бир аз дем чыгардык. Алар: «Эми, Нео, сен кунг-фу билесиң! Эми биздин тажрыйбабыз сиздин экраныңызда. Эми аны колдоно аласыз." [макала]

Журналдын консолидациясы

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Жалпысынан алганда, статистиканы чогулта ала турган стандарттуу модуль бар, бирок аны конфигурацияда активдештирүү керек - бул pg_stat_statements модулу. Бирок ал бизге туура келбеди.

Биринчиден, ал бир эле маалымат базасында ар кандай схемаларды колдонуу менен бир эле суроого дайындайт ар кандай QueryIds. Башкача айтканда, биринчи кылсаңыз SET search_path = '01'; SELECT * FROM user LIMIT 1;андан кийин SET search_path = '02'; жана ошол эле өтүнүч, анда бул модулдун статистикасы ар кандай жазууларга ээ болот, жана мен схемаларды эске албаганда, бул суроо профилинин контекстинде атайын жалпы статистиканы чогулта албайм.

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

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Ошондуктан биз копи-паста менен күрөшүүнү чечип, жаза баштадык жыйноочу.

Коллектор SSH аркылуу туташып, сертификаттын жардамы менен маалымат базасы менен серверге коопсуз байланышты орнотот жана tail -F журнал файлында ага "жабышат". Ошентип, бул сессияда биз журнал файлынын толук "күзгүсүн" алабыз, сервер түзүүчү. Сервердеги жүктүн өзү минималдуу, анткени биз ал жерде эч нерсени талдабайбыз, жөн гана трафикти чагылдырабыз.

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

Демек, биз эки байланышты "узарабыз": биринчиси журналдын өзүн "угуу" жана аны өзүбүзгө алуу, экинчиси мезгил-мезгили менен базадан сурап туруу. "Бирок журнал oid 123 менен белги бөгөттөлгөн экенин көрсөтүп турат", бирок бул иштеп чыгуучуга эч нерсе билдирбейт жана маалымат базасынан: "Ошондой эле OID = 123 деген эмне?" Ошентип, биз мезгил-мезгили менен өзүбүз жөнүндө билбеген нерселерди базадан сурап турабыз.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

"Сиз эске албаган бир гана нерсе бар, пилге окшош аарылардын бир түрү бар!.." Биз 10 серверди көзөмөлдөгүбүз келгенде бул системаны иштеп баштадык. Биздин түшүнүгүбүздө эң маанилүү, бул жерде чечүү кыйын болгон кээ бир көйгөйлөр пайда болду. Бирок биринчи кварталдын ичинде мониторинг жүргүзүү үчүн жүз алдык – система иштегендиктен, бардыгы муну каалашкан, бардыгы ыңгайлуу болчу.

Мунун баарын кошуу керек, маалымат агымы чоң жана активдүү. Чынында, биз эмнени көзөмөлдөйбүз, эмне менен күрөшө алабыз, ошону колдонобуз. Биз PostgreSQLди маалымат сактагыч катары да колдонобуз. Ал эми эч нерсе операторго караганда, ага маалыматтарды "куюп" тезирээк COPY Азыр эмес.

Бирок жөн гана маалыматтарды "куюу" биздин технология эмес. Анткени жүз серверде секундасына болжол менен 50 миң сурооңуз болсо, анда бул күнүнө 100-150 ГБ журналдарды жаратат. Ошондуктан, биз базаны кылдаттык менен "кесүүгө" туура келди.

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

Экинчиден, биз үйрөндүк (мажбур болгон) колдонуу менен жазуу үчүн абдан, абдан тез COPY. Башкача айтканда, жөн эле эмес COPYанткени ал тезирээк INSERT, жана андан да тезирээк.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Үчүнчү пункт - мен керек болчу триггерлерден жана чет өлкөлүк ачкычтардан баш тартуу. Башкача айтканда, бизде эч кандай референттик бүтүндүгү жок. Анткени сизде FK жуптары бар таблица болсо жана сиз маалымат базасынын түзүмүндө "бул жерде FK тарабынан шилтемеленген журнал жазуусу, мисалы, жазуулар тобуна" деп айтсаңыз, анда сиз аны киргизгенде PostgreSQL, аны кантип алып, чынчыл кылуудан башка эч нерсеси жок SELECT 1 FROM master_fk1_table WHERE ... Сиз киргизүүгө аракет кылып жаткан идентификатор менен - ​​жөн гана бул жазуу бар экенин текшерүү үчүн, бул Чет өлкөлүк ачкычты кыстаруу менен "үзүп салбаңыз".

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

Кийинки пункт - топтоо жана хэширлөө. Башында, биз аларды маалымат базасында ишке ашырдык - акыры, жазуу келгенде, аны дароо планшеттин кандайдыр бир түрү менен жасоо ыңгайлуу триггерде "плюс бир". Ооба, бул ыңгайлуу, бирок ошол эле жаман нерсе - сиз бир жазууну киргизесиз, бирок башка таблицадан башка нерсени окуп жана жазууга аргасыз болосуз. Анын үстүнө, сиз окуп-жаза эле эмес, ар дайым жасайсыз.

Эми сизде белгилүү бир хост аркылуу өткөн сурамдардын санын эсептеп турган таблица бар деп элестетиңиз: +1, +1, +1, ..., +1. Ал эми сизге, негизинен, мунун кереги жок - мунун баары мүмкүн жыйноочу боюнча эскерүү суммасы жана бир жолу маалымат базасына жөнөтүү +10.

Ооба, кандайдыр бир көйгөйлөр жаралса, сиздин логикалык бүтүндүгүңүз "ыдырап кетиши" мүмкүн, бирок бул дээрлик реалдуу эмес учур - анткени сизде кадимки сервер бар, анын контроллерунда батареясы бар, сизде транзакциялар журналы, логикалык журнал бар. файл системасы... Жалпысынан алганда, бул татыктуу эмес. Триггерлерди/ФКны иштетүүдөн алынган өндүрүмдүүлүктү жоготуу сиз тарткан чыгашага татыктуу эмес.

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

Тексттен MD5ти колдонуу биз үчүн эң сонун болду - суроо-талап, план, шаблон,... Биз аны коллектор тарапка эсептеп, даяр ID-ди базага “төктөбүз”. MD5 узундугу жана күнүмдүк бөлүү мүмкүн болгон кагылышуулар жөнүндө тынчсызданбоого мүмкүндүк берет.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

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

Адатта маалыматты кантип жазасыз? Бизде кандайдыр бир берилиштер топтому бар, аны бир нече таблицага бөлүп, анан КӨЧҮРҮП алабыз – адегенде биринчиге, анан экинчиге, үчүнчүгө... Бул ыңгайсыз, анткени биз үч кадам менен бир маалымат агымын жазып жаткандайбыз. ырааттуу. Жагымсыз. Муну тезирээк жасоого болобу? мүмкүн!

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Башкача айтканда, коллектордо ар дайым агым бар, ага мен керектүү маалыматтарды жаза алам. Бирок маалымат базасы бул маалыматтарды көрүп, кимдир бирөө бул маалыматтардын жазылышын күтүп тыгылып калбашы үчүн, КӨЧҮРҮҮ белгилүү бир аралыкта үзгүлтүккө учурашы керек. Биз үчүн эң эффективдүү мезгил болжол менен 100 мс болду - биз аны жаап, ошол эле столго кайра ачабыз. Ал эми кээ бир чокуларда бир агым жетишсиз болсо, анда биз белгилүү бир чекке чейин топтойбуз.

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

Мындай аномалиялардан кутулуу үчүн, жөн гана эч нерсени бириктирбеңиз, такыр буфер кылба. Жана эгер дискке буферлөө орун алса (бактыга жараша, Node.js ичиндеги Stream API сизге билүүгө мүмкүндүк берет) - бул байланышты кийинкиге калтырыңыз. Кайрадан бекер болгон окуяны алганыңызда, ага топтолгон кезектен жазыңыз. Ал бош эмес болсо, бассейнден кийинки бекерди алып, ага жазыңыз.

Маалыматтарды жазууга бул ыкманы киргизгенге чейин бизде болжол менен 4K жазуу операциясы болгон жана ушундай жол менен жүктү 4 эсеге азайттык. Эми алар жаңы мониторингге алынган маалымат базаларынын эсебинен дагы 6 эсеге өстү - 100 МБ/сек чейин. Эми биз акыркы 3 айдагы журналдарды болжол менен 10-15 ТБ көлөмүндө сактайбыз, үч айдын ичинде ар бир иштеп чыгуучу кандайдыр бир көйгөйдү чече алат деп үмүттөнөбүз.

Биз көйгөйлөрдү түшүнөбүз

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Бирок миллиондор башкарылбайт, биз адегенде "кичинекей" кылышыбыз керек. Жана, биринчи кезекте, сиз бул "кичинекей" нерсени кантип уюштурууну чечишиңиз керек.

Биз үч негизги пунктту аныктадык:

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

Бизге суроо-талапты "ким" жөнөткөнүн түшүнүү үчүн биз стандарттык куралды колдонобуз - сеанс өзгөрмөсүн орнотуу: SET application_name = '{bl-host}:{bl-method}'; — биз суроо-талап келген бизнес-логикалык хосттун атын жана аны демилгелеген ыкманын же колдонмонун атын жөнөтөбүз.

Сурамдын "ээсинен" өткөндөн кийин, ал журналга чыгышы керек - бул үчүн биз өзгөрмөлөрдү конфигурациялайбыз log_line_prefix = ' %m [%p:%v] [%d] %r %a'. Кызыккандар үчүн, балким колдонмону карагыламунун баары эмнени билдирет. Көрсө, биз журналдан көрөбүз:

  • время
  • процесс жана транзакция идентификаторлору
  • базанын аты
  • Бул суроону жөнөткөн адамдын IP
  • жана методдун аталышы

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

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

Ошентип, бул жерде кесүү "бир сервер - бир күн" бизге кандайдыр бир анализ үчүн жетиштүү болуп чыкты.

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

Биз конкреттүү инстанциялардан калыптарга өткөндө, биз бир эле учурда эки артыкчылыкка ээ болдук:

  • талдоо үчүн объекттердин санын бир нече жолу кыскартуу
    Биз көйгөйдү мындан ары миңдеген суроо же пландар менен эмес, ондогон шаблондор боюнча талдап чыгышыбыз керек.
  • хронологиясы
    Башкача айтканда, белгилүү бир бөлүмдүн ичинде "факттарды" жалпылоо менен, сиз күндүз алардын көрүнүшүн көрсөтө аласыз. Жана бул жерден түшүнсө болот, эгер сизде кандайдыр бир үлгү болсо, мисалы, саатына бир жолу, бирок ал күнүнө бир жолу болушу керек болсо, анда эмне туура эмес болгонун ойлонушуңуз керек - ким жана эмне үчүн, балким бул жерде болушу керек. болбошу керек. Бул дагы бир сандык эмес, таза визуалдык талдоо ыкмасы.

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

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

Анткени, мисалы, сиз хосттун аналитика барагына келдиңиз, караңыз - дискте бир нерсе өтө көп окуй баштады. Сервердеги диск аны көтөрө албайт - аны ким окуйт?

Жана сиз каалаган тилке боюнча сорттоп, азыр эмне менен алектенээриңизди чече аласыз - процессорго же дискке жүктөлгөн жүк, же суроо-талаптардын жалпы саны... Биз аны иреттеп, "жогорку" дегендерин карап чыктык, оңдодук жана колдонмонун жаңы версиясын чыгарды.
[видеолекция]

Жана ошол замат сыяктуу өтүнүчтөн бир эле шаблон менен келген ар кандай тиркемелерди көрө аласыз SELECT * FROM users WHERE login = 'Vasya'. Frontend, backend, processing... Жана эгер ал аны менен байланышпаса, иштетүү эмне үчүн колдонуучуну окуйт деп таң каласыз.

Тескерисинче, колдонмонун эмне кылып жатканын дароо көрүү. Мисалы, frontend бул, бул, бул жана бул саатына бир жолу (хронология жардам берет). Анан дароо эле суроо туулат: саатына бир жолу бир нерсе кылуу фронттун иши эмес окшойт...

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Бир нече убакыт өткөндөн кийин, биз топтоо жетишсиз экенин түшүндүк план түйүндөрү боюнча статистика. Биз пландардан таблицалардын маалыматтары менен бир нерсе кылган түйүндөрдү гана бөлүп алдык (аларды индекс боюнча окуу/жазуу же жокпу). Чынында, мурунку сүрөткө салыштырмалуу бир гана аспект кошулат - бул түйүн бизге канча рекордду алып келди?, жана канчасы жок кылынды (Сатарлар чыпка аркылуу алынып салынды).

Пластинкада ылайыктуу индекс жок, сиз ага өтүнүч келтиресиз, ал индекстин жанынан учуп өтүп, Seq Scanга түшөт... сиз бирөөсүн кошпогондо бардык жазууларды чыпкаладыңыз. Эмне үчүн сизге күнүнө 100 миллион чыпкаланган жазуу керек? Индексти топтоо жакшы эмеспи?

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

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

Суроолорду жазгандардын баары, кыязы, мындай үлгүгө туш болушса керек: “Мага Васяга акыркы буйрукту, анын датасын бериңиз.” А эгер сизде датасы боюнча индекс жок болсо же сиз колдонгон индексте дата жок болсо, анда сиз так ошол эле "тырмоо" боюнча бас.

Бирок биз бул "тырмоо" экенин билебиз - анда эмне үчүн иштеп чыгуучуга эмне кылуу керек экенин дароо айтпай эле коёлу. Демек, азыр планды ачып жатканда, биздин иштеп чыгуучубуз дароо кеңештери бар кооз сүрөттү көрөт, алар ага дароо: "Сизде бул жерде жана бул жерде көйгөйлөр бар, бирок алар тигил же бул жол менен чечилет" деп айтышат.

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

PostgreSQL сурамдарын жапырт оптималдаштыруу. Кирилл Боровиков (тензор)

Source: www.habr.com

Комментарий кошуу