PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Тайлан нь зөвшөөрөгдсөн зарим хандлагыг танилцуулав Өдөрт хэдэн сая асуулга байгаа үед SQL асуулгын гүйцэтгэлийг хянах, мөн хяналтанд байдаг хэдэн зуун PostgreSQL серверүүд байдаг.

Техникийн ямар шийдэл нь ийм хэмжээний мэдээллийг үр дүнтэй боловсруулах боломжийг бидэнд олгодог бөгөөд энэ нь энгийн хөгжүүлэгчийн амьдралыг хэрхэн хөнгөвчлөх вэ?


Хэн сонирхож байна вэ? тодорхой асуудлуудын дүн шинжилгээ, янз бүрийн оновчлолын арга SQL асуулга болон PostgreSQL дэх ердийн DBA асуудлыг шийдвэрлэх - та бас хийж болно цуврал нийтлэлүүдийг уншина уу энэ сэдэв дээр.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)
Намайг Кирилл Боровиков гэдэг, би төлөөлж байна Тензор компани. Тодруулбал, би манай компанид мэдээллийн сантай ажиллах чиглэлээр мэргэшсэн.

Өнөөдөр би танд ганц асуулгын гүйцэтгэлийг "тусгаарлах" шаардлагагүй, харин асуудлыг бөөнөөр нь шийдэх үед бид асуулга хэрхэн оновчтой болгох талаар хэлэх болно. Олон сая хүсэлт байгаа үед та заримыг нь олох хэрэгтэй шийдвэрлэх арга замууд энэ том асуудал.

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

Тэд бүгд хэвийн ажиллаж, хөгжихийн тулд бид улс даяар 10 хөгжлийн төвтэй бөгөөд тэдгээрийн дотор илүү олон байдаг 1000 хөгжүүлэгчид.

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

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

SQL бол тунхаглах хэл юм. Та ямар нэг зүйл "хэрхэн" ажиллах ёстойг биш, харин "юунд" хүрэхийг хүсч байгаагаа дүрсэлдэг. DBMS нь хэрхэн JOIN хийхийг илүү сайн мэддэг - хүснэгтээ хэрхэн холбох, ямар нөхцөл тавих, индексээр юу орох, юу болохгүй вэ ...

Зарим DBMS нь "Үгүй ээ, энэ хоёр хүснэгтийг ийм дараалалд холбоно уу" гэсэн зөвлөмжийг хүлээн авдаг боловч PostgreSQL үүнийг хийж чадахгүй. Энэ бол тэргүүлэх хөгжүүлэгчдийн ухамсартай байр суурь юм: "Бид хөгжүүлэгчдэд ямар нэгэн зөвлөмж ашиглахыг зөвшөөрөхөөс илүү асуулга оновчтой болгох ажлыг дуусгахыг илүүд үздэг."

Гэсэн хэдий ч PostgreSQL нь "гаднаас" өөрийгөө хянах боломжийг олгодоггүй ч энэ нь төгс боломжийг олгодог. түүний дотор юу болж байгааг хараарайта асуулга явуулах үед, хаана асуудалтай байгаа.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Ерөнхийдөө хөгжүүлэгч [DBA-д] ихэвчлэн ямар сонгодог асуудал тулгардаг вэ? “Энд бид хүсэлтийг биелүүлсэн, мөн Манайд бүх зүйл удаан байна, бүх зүйл өлгөөтэй байна, ямар нэг зүйл болж байна ... Ямар нэг асуудал байна!"

Шалтгаан нь бараг үргэлж ижил байдаг:

  • үр ашиггүй асуулгын алгоритм
    Хөгжүүлэгч: "Одоо би түүнд JOIN-ээр дамжуулан SQL-д 10 хүснэгт өгч байна..." - түүний нөхцөл байдал гайхамшигтайгаар үр дүнтэй "тайлагдах" бөгөөд тэр бүх зүйлийг хурдан авах болно гэж найдаж байна. Гэхдээ гайхамшиг тохиолддоггүй бөгөөд ийм хувьсах чадвартай аливаа систем (нэг FROM-д 10 хүснэгт) үргэлж ямар нэгэн алдаа гаргадаг. [нийтлэл]
  • хуучирсан статистик
    Энэ цэг нь PostgreSQL-д маш их хамааралтай бөгөөд та сервер дээр том өгөгдлийн багцыг "цутгаж", хүсэлт гаргаснаар таны таблетыг "секскантай" болно. Учир нь өчигдөр 10 бичлэг байсан бол өнөөдөр 10 сая болсон ч PostgreSQL үүнийг хараахан мэдээгүй байгаа тул бид энэ тухай хэлэх хэрэгтэй байна. [нийтлэл]
  • нөөц дээр "залгах"
    Та хангалттай хэмжээний диск, санах ой, процессорын ажиллагаагүй сул сервер дээр том бөгөөд ачаалал ихтэй мэдээллийн сан суулгасан байна. Ингээд л... Хаа нэгтээ дээшээ үсрэх боломжгүй гүйцэтгэлийн тааз байдаг.
  • блоклох
    Энэ бол хэцүү цэг боловч тэдгээр нь янз бүрийн өөрчлөх асуулгад хамгийн их хамааралтай (INSERT, UPDATE, DELETE) - энэ бол тусдаа том сэдэв юм.

Төлөвлөгөө авч байна

...Бас бусад бүх зүйлийн хувьд бид төлөвлөгөө хэрэгтэй! Бид сервер дотор юу болж байгааг харах хэрэгтэй.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

PostgreSQL-д зориулсан асуулгын гүйцэтгэлийн төлөвлөгөө нь текст дүрслэл дэх асуулга гүйцэтгэх алгоритмын мод юм. Төлөвлөгчдийн хийсэн шинжилгээний үр дүнд яг энэ алгоритм нь хамгийн үр дүнтэй болох нь тогтоогдсон юм.

Модны зангилаа бүр нь үйлдлүүд юм: хүснэгт эсвэл индексээс өгөгдөл авах, битийн зураг үүсгэх, хоёр хүснэгтийг нэгтгэх, нэгдэх, огтлолцох, сонгохыг хасах. Асуултыг гүйцэтгэх нь энэ модны зангилаа дундуур алхах явдал юм.

Асуулгын төлөвлөгөөг авахын тулд хамгийн хялбар арга бол мэдэгдлийг гүйцэтгэх явдал юм EXPLAIN. Бүх бодит шинж чанаруудыг олж авахын тулд, өөрөөр хэлбэл үндсэн дээр асуулга гүйцэтгэх - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

Муу тал: та үүнийг ажиллуулахад "энд, одоо" тохиолддог тул энэ нь зөвхөн орон нутгийн дибаг хийхэд тохиромжтой. Хэрэв та өгөгдлийн өөрчлөлтийн хүчтэй урсгалын дор байгаа өндөр ачаалалтай серверийг авбал: "Өө! Энд бид удаан гүйцэтгэлтэй байнаси хүсэлт." Хагас цаг, нэг цагийн өмнө - таныг ажиллуулж, бүртгэлээс энэ хүсэлтийг авч, серверт буцааж авчрах үед таны өгөгдлийн багц болон статистик бүхэлдээ өөрчлөгдсөн. Та дибаг хийхийн тулд үүнийг ажиллуулж, хурдан ажилладаг! Тэгээд яагаад, яагаад гэдгийг ойлгохгүй байна байсан аажмаар

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Хүсэлтийг сервер дээр гүйцэтгэх үед яг юу болсныг ойлгохын тулд ухаалаг хүмүүс бичжээ auto_explain модуль. Энэ нь бараг бүх нийтлэг PostgreSQL түгээлтэд байдаг бөгөөд тохиргооны файлд идэвхжүүлж болно.

Хэрэв энэ нь зарим хүсэлт таны хэлсэн хязгаараас илүү удаан ажиллаж байгааг ойлговол энэ нь тийм болно Энэхүү хүсэлтийн төлөвлөгөөний "хормын хувилбар"-ыг авч, бүртгэлд хамт бичнэ.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Одоо бүх зүйл зүгээр юм шиг байна, бид дүнзэн дээр очоод тэнд харна... [хөлний даавуу бичвэр]. Гэхдээ үүнийг хэрэгжүүлэхэд 11 мс зарцуулсан тул маш сайн төлөвлөгөө гэдгээс өөр юу ч хэлж чадахгүй.

Бүх зүйл сайхан байгаа мэт боловч яг юу болсон нь тодорхойгүй байна. Ерөнхий цаг хугацаанаас гадна бид юу ч харахгүй байна. Яагаад гэвэл ийм энгийн бичвэрийн "хурга" -ыг харах нь ерөнхийдөө харагдахгүй байна.

Хэдийгээр энэ нь тодорхойгүй, тохиромжгүй байсан ч илүү үндсэн асуудлууд байдаг:

  • Зангилаа заана бүхэл бүтэн дэд модны нөөцийн нийлбэр түүний доор. Өөрөөр хэлбэл, хэрэв та энэ индексийн сканнерд ямар нэг үүрлэсэн нөхцөл байгаа бол хэр их цаг зарцуулсныг олж мэдэх боломжгүй юм. Бид дотроо "хүүхдүүд" болон нөхцөлт хувьсагч, CTE байгаа эсэхийг динамикаар хайж, энэ бүгдийг "бидний оюун ухаанд" хасах хэрэгтэй.
  • Хоёр дахь цэг: зангилаа дээр заасан цаг нэг зангилааны гүйцэтгэлийн хугацаа. Хэрэв энэ зангилаа нь жишээлбэл, хүснэгтийн бичлэгийг хэд хэдэн удаа давталтын үр дүнд гүйцэтгэсэн бол энэ зангилааны мөчлөгийн давталтын тоо төлөвлөгөөнд нэмэгддэг. Гэхдээ атомын гүйцэтгэлийн хугацаа нь төлөвлөгөөний хувьд ижил хэвээр байна. Өөрөөр хэлбэл, энэ зангилаа нийтдээ хэр удаан хийгдсэнийг ойлгохын тулд та нэг зүйлийг нөгөөгөөр үржүүлэх хэрэгтэй - дахин "толгойдоо".

Ийм нөхцөлд "Хамгийн сул холбоос нь хэн бэ?" Гэж ойлгоорой. бараг боломжгүй. Тиймээс хөгжүүлэгчид өөрсдөө "гарын авлага" дээр үүнийг бичдэг "Төлөвлөгөөг ойлгох нь суралцах ёстой урлаг, туршлага ...".

Гэхдээ бид 1000 хөгжүүлэгчтэй бөгөөд та энэ туршлагыг тус бүрт нь хүргэж чадахгүй. Би, чи, тэр мэднэ, гэхдээ тэнд байгаа хэн нэгэн нь мэдэхгүй. Магадгүй тэр сурах ч юм уу, үгүй ​​ч юм уу, гэхдээ тэр одоо ажиллах шаардлагатай байна - тэр энэ туршлагыг хаанаас авах вэ?

Төлөвлөгөөний дүрслэл

Тиймээс эдгээр асуудлыг шийдвэрлэхийн тулд бидэнд хэрэгтэй гэдгийг ойлгосон төлөвлөгөөний сайн дүрслэл. [нийтлэл]

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Бид эхлээд "зах зээлээр" явсан - одоо юу байгааг харахын тулд интернетээс харцгаая.

Гэхдээ харьцангуй "амьд" шийдлүүд маш цөөхөн, бага багаар хөгжиж байгаа нь тодорхой болсон - шууд утгаараа зөвхөн нэг нь: description.depesz.com Хуберт Любачевски. Төлөвлөгөөний текстийн дүрслэлийг "тэжээх" талбарт оруулахад танд задлан шинжлэгдсэн өгөгдөл бүхий хүснэгтийг харуулна.

  • зангилааны өөрийн боловсруулах хугацаа
  • бүхэл бүтэн дэд модны нийт хугацаа
  • статистикийн тооцоогоор олж авсан бичлэгийн тоо
  • зангилааны бие өөрөө

Энэ үйлчилгээ нь холбоосын архивыг хуваалцах чадвартай. Та төлөвлөгөөгөө тэнд шидээд: "Хөөе, Вася, энд холбоос байна, ямар нэг зүйл буруу байна" гэж хэлэв.

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 Generation эсвэл Seq Scan ямар нэгэн тэмдгийн дагуу.

Энэ бол бидний нэрлэсэн товчилсон дүрслэл юм төлөвлөгөөний загвар.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Өөр юу тохиромжтой байх вэ? Бидний нийт цагийн хэдэн хувийг аль зангилаанд хуваарилж байгааг харах нь тохиромжтой байх болно - зүгээр л хажуу тийшээ "наад" бялуу хүснэгт.

Бид зангилаа руу чиглүүлж харна уу - Seq Scan нь нийт цагийн дөрөвний нэгээс бага хувийг авсан бөгөөд үлдсэн 3/4-ийг CTE Scan авсан байна. Аймшиг! Энэ бол CTE Scan-ийн "галын хурд"-ын талаархи жижиг тэмдэглэл бөгөөд хэрэв та тэдгээрийг асуулгадаа идэвхтэй ашигладаг бол. Тэд тийм ч хурдан биш - ердийн хүснэгт сканнераас ч доогуур байдаг. [нийтлэл] [нийтлэл]

Гэхдээ ихэвчлэн ийм диаграммууд нь илүү сонирхолтой, илүү төвөгтэй байдаг бөгөөд бид тэр даруй сегмент рүү чиглүүлж, жишээ нь Seq Scan-ийн хагасаас илүүг нь "идсэн" болохыг олж хардаг. Түүгээр ч барахгүй, дотор нь ямар нэгэн шүүлтүүр байсан, үүний дагуу маш олон бичлэгүүд хаягдсан ... Та энэ зургийг хөгжүүлэгч рүү шууд шидэж, "Вася, энд бүх зүйл танд муу байна! Ойлго, хар, ямар нэг зүйл буруу байна!"

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Мэдээжийн хэрэг, зарим "тармуурууд" оролцсон.

Бидний тааралдсан хамгийн эхний зүйл бол дугуйлах асуудал байв. Төлөвлөгөөний бие даасан зангилаа бүрийн цагийг 1 μs нарийвчлалтайгаар зааж өгсөн болно. Зангилааны мөчлөгийн тоо жишээлбэл, 1000-аас давсан үед - PostgreSQL-ийг хэрэгжүүлсний дараа "нарийвчлалын хүрээнд" хуваагдсан бол буцааж тооцоолохдоо бид "0.95 мс-ээс 1.05 мс хооронд" нийт цагийг авдаг. Тооцоолол микросекундэд хүрэхэд зүгээр, гэхдээ аль хэдийн [милл] секунд болоход та "хэн хэр их зарцуулсан" төлөвлөгөөний зангилаа руу нөөцийг "тайлах" үед энэ мэдээллийг анхаарч үзэх хэрэгтэй.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Хоёрдахь цэг, илүү төвөгтэй зүйл бол динамик зангилааны хооронд нөөцийг (эдгээр буфер) хуваарилах явдал юм. Энэ нь бидэнд прототипийн эхний 2 долоо хоног, нэмж 4 долоо хоног зарцуулсан.

Энэ төрлийн асуудлыг шийдэх нь маш амархан - бид CTE хийж, түүн дээр ямар нэг зүйлийг уншдаг. Үнэн хэрэгтээ PostgreSQL нь "ухаалаг" бөгөөд тэнд юу ч уншихгүй. Дараа нь бид түүнээс анхны бичлэгийг, мөн ижил CTE-ээс зуун анхны бичлэгийг авдаг.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Бид төлөвлөгөөг хараад ойлголоо - хачирхалтай нь бид Seq Scan-д 3 буфер (өгөгдлийн хуудас), CTE Scan-д 1, хоёр дахь CTE Scan-д өөр 2 "хэрэглэсэн" байна. Өөрөөр хэлбэл, бүх зүйлийг нэгтгэн дүгнэвэл бид 6-г авах болно, гэхдээ таблетаас бид зөвхөн 3-ыг уншдаг! CTE Scan нь хаанаас ч юу ч уншдаггүй, харин процессын санах ойтой шууд ажилладаг. Энэ нь энд ямар нэг зүйл буруу байгаа нь тодорхой байна!

Үнэн хэрэгтээ, Seq Scan-аас хүссэн 3 хуудас мэдээлэл байгаа бөгөөд эхлээд 1-ийг нь 1-р CTE Scan-ыг хүссэн, дараа нь 2-р, өөр 2-ыг нь уншсан. Өөрөөр хэлбэл, нийт 3 хуудас биш харин 6 хуудсыг уншсан.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Энэхүү зураг нь төлөвлөгөөний хэрэгжилт нь мод байхаа больсон, зүгээр л нэг төрлийн цикл бус график юм гэдгийг ойлгоход хүргэсэн. Бид ийм диаграммыг авсан бөгөөд ингэснээр бид "эхлээд хаанаас ирсэн" гэдгийг ойлгох болно. Өөрөөр хэлбэл, энд бид pg_class-аас CTE үүсгээд 2 удаа гуйж, 101 дахь удаагаа авахыг хүсэхэд бараг бүх цаг мөчид зарцуулагдсан. 1-р оруулгыг унших нь таблетаас XNUMX-р оруулгыг уншихаас хамаагүй илүү үнэтэй гэдэг нь ойлгомжтой.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Бид хэсэг хугацаанд амьсгалаа гаргалаа. Тэд: "Одоо, Нео, чи кунг-фуг мэднэ! Одоо бидний туршлага таны дэлгэцэн дээр байна. Одоо та үүнийг ашиглаж болно." [нийтлэл]

Лог нэгтгэх

Манай 1000 хөгжүүлэгчид тайвширсан. Гэхдээ бид зөвхөн хэдэн зуун "байлдааны" сервертэй гэдгийг ойлгосон бөгөөд хөгжүүлэгчид энэ бүх "хуулбар буулгах" нь тийм ч тохиромжтой биш юм. Бид өөрсдөө цуглуулах ёстой гэдгийг ойлгосон.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Ерөнхийдөө статистик мэдээлэл цуглуулах стандарт модуль байдаг, гэхдээ үүнийг тохиргоонд идэвхжүүлэх шаардлагатай байдаг. pg_stat_statements модуль. Гэхдээ тэр бидэнд тохирохгүй байсан.

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

Биднийг ашиглахад саад болсон хоёр дахь зүйл бол төлөвлөгөө дутагдалтай. Энэ нь ямар ч төлөвлөгөө байхгүй, зөвхөн хүсэлт нь өөрөө байдаг. Юу удааширч байгааг бид харж байгаа ч яагаад гэдгийг ойлгохгүй байна. Энд бид хурдацтай өөрчлөгдөж буй өгөгдлийн багцын асуудал руу буцаж ирлээ.

Тэгээд сүүлчийн мөч - "баримт" дутмаг. Өөрөөр хэлбэл, та асуулгын гүйцэтгэлийн тодорхой тохиолдлыг шийдвэрлэх боломжгүй - байхгүй, зөвхөн нэгтгэсэн статистик байдаг. Хэдийгээр үүнтэй ажиллах боломжтой ч энэ нь маш хэцүү байдаг.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Тиймээс бид copy-paste-тэй тэмцэхээр шийдэж, бичиж эхэлсэн цуглуулагч.

Коллектор нь 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.

Тиймээ, зарим асуудал гарсан тохиолдолд таны логик бүрэн бүтэн байдал "унаж" магадгүй, гэхдээ энэ нь бараг бодит бус тохиолдол юм - учир нь та ердийн сервертэй, энэ нь хянагчдаа батерейтай, гүйлгээний бүртгэл, бүртгэлтэй. файлын систем ... Ерөнхийдөө энэ нь үнэ цэнэтэй зүйл биш юм. Триггер/FK ажиллуулснаар таны олж буй бүтээмжийн алдагдал нь таны гаргасан зардалд үнэ цэнэтэй зүйл биш юм.

Хэшингийн хувьд ч мөн адил. Тодорхой хүсэлт танд ирж, та мэдээллийн санд тодорхой танигчийг тооцоолж, мэдээллийн санд бичээд дараа нь хүн бүрт хэлээрэй. Бичлэг хийх үед ижил зүйлийг бичихийг хүссэн хоёр дахь хүн тан дээр ирэх хүртэл бүх зүйл хэвийн байгаа бөгөөд та хаагдах болно, энэ нь аль хэдийн муу байна. Тиймээс, хэрэв та зарим ID үүсгэхийг үйлчлүүлэгч рүү (мэдээллийн сантай холбоотой) шилжүүлэх боломжтой бол үүнийг хийх нь дээр.

Текстээс MD5-ийг ашиглах нь бидний хувьд зүгээр л төгс байсан - хүсэлт, төлөвлөгөө, загвар, ... Бид үүнийг цуглуулагч тал дээр тооцоолж, бэлэн ID-г мэдээллийн санд "асгадаг". MD5-ийн урт ба өдөр тутмын хуваалт нь болзошгүй мөргөлдөөний талаар санаа зовохгүй байх боломжийг бидэнд олгодог.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Гэхдээ энэ бүгдийг хурдан бичихийн тулд бичлэг хийх журмыг өөрөө өөрчлөх шаардлагатай болсон.

Та ихэвчлэн өгөгдлийг хэрхэн бичдэг вэ? Бидэнд ямар нэгэн өгөгдлийн багц байгаа, бид үүнийг хэд хэдэн хүснэгтэд хувааж, дараа нь ХУУЛАХ - эхлээд эхний, дараа нь хоёр дахь, гурав дахь ... Энэ нь тохиромжгүй, учир нь бид нэг өгөгдлийн урсгалыг гурван алхамаар бичиж байх шиг байна. дараалсан. Тааламжгүй. Үүнийг илүү хурдан хийж чадах уу? Чадах!

Үүнийг хийхийн тулд эдгээр урсгалыг бие биетэйгээ зэрэгцүүлэн задлахад л хангалттай. Бидэнд алдаа, хүсэлт, загвар, хаалт, ... тусдаа хэлхээнд нисч байгаа нь харагдаж байна - бид бүгдийг зэрэгцүүлэн бичдэг. Үүнд хангалттай Хуулбарлах сувгийг зорилтот хүснэгт бүрт байнга нээлттэй байлгах.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Энэ нь цуглуулагч дээр үргэлж урсгал байдаг, үүн рүү би хэрэгтэй мэдээллээ бичиж болно. Гэхдээ мэдээллийн сан энэ өгөгдлийг харж, хэн нэгэн энэ өгөгдлийг бичихийг хүлээж гацахгүйн тулд, COPY нь тодорхой интервалтайгаар тасалдсан байх ёстой. Бидний хувьд хамгийн үр дүнтэй хугацаа нь ойролцоогоор 100 мс байсан - бид үүнийг хааж, тэр даруй ижил хүснэгтэд дахин нээдэг. Мөн зарим оргил үед бидэнд нэг урсгал хангалтгүй байвал бид тодорхой хязгаар хүртэл нэгтгэдэг.

Нэмж дурдахад, ийм ачааллын профайлын хувьд бүртгэлийг багцаар нь цуглуулсан аливаа нэгтгэл нь муу зүйл гэдгийг бид олж мэдсэн. Сонгодог муу юм INSERT ... VALUES болон цаашлаад 1000 бичлэг. Учир нь тэр үед та зөөвөрлөгч дээр бичих оргил үетэй тул диск рүү ямар нэгэн зүйл бичихийг оролдсон бүх хүмүүс хүлээж байх болно.

Ийм гажигийг арилгахын тулд юу ч бүү нэгтгэ, огт буфер бүү хий. Хэрэв дискэнд буфер хийх тохиолдол гарвал (аз болоход Node.js дээрх Stream API нь танд үүнийг мэдэх боломжийг олгоно) - энэ холболтыг хойшлуул. Та дахин үнэ төлбөргүй үйл явдал хүлээн авбал хуримтлагдсан дарааллаас түүнд бичээрэй. Завгүй байхад усан сангаас дараагийн үнэгүй нэгийг аваад түүн рүү бичээрэй.

Өгөгдөл бүртгэх энэ аргыг нэвтрүүлэхээс өмнө бид ойролцоогоор 4K бичих ажиллагаатай байсан бөгөөд ийм байдлаар ачааллыг 4 дахин бууруулсан. Одоо тэд шинэ хяналттай мэдээллийн баазын ачаар дахин 6 дахин өссөн - 100MB/s хүртэл. Одоо бид сүүлийн 3 сарын турш логуудыг 10-15 TB-ийн багтаамжтай хадгалдаг бөгөөд гуравхан сарын дотор ямар ч хөгжүүлэгч аливаа асуудлыг шийдэж чадна гэж найдаж байна.

Асуудлыг бид ойлгож байна

Гэхдээ зүгээр л энэ бүх өгөгдлийг цуглуулах нь сайн, хэрэгтэй, хамааралтай, гэхдээ хангалттай биш - үүнийг ойлгох хэрэгтэй. Учир нь эдгээр нь өдөрт хэдэн сая өөр төлөвлөгөө байдаг.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Гэхдээ сая сая хүнийг удирдах боломжгүй тул бид эхлээд "жижиг" хийх ёстой. Юуны өмнө та энэ "жижиг" зүйлийг хэрхэн зохион байгуулахаа шийдэх хэрэгтэй.

Бид гурван гол зүйлийг тодорхойлсон:

  • хэн байна энэ хүсэлтийг илгээсэн
    Энэ нь ямар програмаас "ирсэн" вэ: вэб интерфэйс, backend, төлбөрийн систем эсвэл өөр зүйл.
  • хаана Энэ нь болсон
    Ямар сервер дээр? Учир нь хэрэв танд нэг програмын дор хэд хэдэн сервер байгаа бөгөөд гэнэт нэг нь "тэнэг" болчихвол (учир нь "диск нь ялзарсан", "санах ой алдагдсан", өөр ямар нэг асуудал гарсан) та серверийг тусгайлан шийдвэрлэх хэрэгтэй.
  • хэрхэн асуудал нэг талаараа илэрсэн

Бидэнд "хэн" хүсэлт илгээснийг ойлгохын тулд бид стандарт хэрэгсэл ашигладаг - сессийн хувьсагчийг тохируулдаг: 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... Хэрэв хэрэглэгч түүнтэй харьцахгүй бол боловсруулалт нь яагаад түүнийг уншина гэж та гайхаж байна.

Эсрэг арга бол програмаас юу хийж байгааг шууд харах явдал юм. Жишээлбэл, урд тал нь энэ, энэ, энэ, мөн энэ нь цагт нэг удаа (хугацаа нь тусалдаг). Тэгээд тэр даруй асуулт гарч ирнэ: цагт нэг удаа ямар нэг зүйл хийх нь урд талын ажил биш юм шиг санагдаж байна ...

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Хэсэг хугацааны дараа бид нэгтгэх чадвар дутмаг байгаагаа ойлгосон төлөвлөгөөний зангилаагаар статистик. Бид зөвхөн хүснэгтийн өгөгдөлтэй ямар нэгэн зүйл хийдэг зангилаануудыг төлөвлөгөөнөөс тусгаарласан (үүнийг индексээр нь унших/бичих). Үнэн хэрэгтээ өмнөх зурагтай харьцуулахад зөвхөн нэг талыг нэмж оруулсан болно - Энэ зангилаа бидэнд хэдэн бичлэг авчирсан бэ?, мөн хэд нь хасагдсан (Мөрүүдийг шүүлтүүрээр арилгасан).

Таны тавган дээр тохирох индекс байхгүй, та түүнд хүсэлт гаргаж, энэ нь индексийн хажуугаар өнгөрч, Seq Scan руу унасан ... та нэгээс бусад бүх бичлэгийг шүүсэн. Яагаад танд өдөрт 100 сая шүүсэн бичлэг хэрэгтэй байна вэ? Индексийг эргүүлэх нь дээр биш гэж үү?

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Бүх төлөвлөгөөг зангилаагаар нь шинжилж үзээд бид төлөвлөгөөнд сэжигтэй харагдах зарим ердийн бүтэц байдгийг ойлгосон. Хөгжүүлэгчид: "Найз аа, энд та эхлээд индексээр уншиж, дараа нь ангилж, дараа нь таслав" гэж хэлэх нь сайхан байх болно - дүрмээр бол нэг бичлэг байдаг.

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

Гэхдээ энэ бол "тармуур" гэдгийг бид мэднэ, тиймээс яагаад хөгжүүлэгчдээ юу хийх ёстойгоо шууд хэлж болохгүй гэж. Үүний дагуу одоо төлөвлөгөөгөө нээхэд манай хөгжүүлэгч тэр даруй зөвлөмж бүхий үзэсгэлэнтэй зургийг олж хардаг бөгөөд тэд тэр даруй түүнд: "Чамд энд тэнд асуудал байгаа, гэхдээ үүнийг ийм байдлаар шийдэж байна" гэж хэлдэг.

Үүний үр дүнд асуудлыг шийдвэрлэхэд шаардлагатай байсан туршлага одоо бол мэдэгдэхүйц буурчээ. Энэ бол бидэнд байгаа ийм хэрэгсэл юм.

PostgreSQL асуулгыг бөөнөөр нь оновчтой болгох. Кирилл Боровиков (тензор)

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх