Хуудаслагдсан асуулгад OFFSET болон LIMIT ашиглахаас зайлсхий

Өгөгдлийн сангийн гүйцэтгэлийг оновчтой болгох талаар санаа зовох шаардлагагүй байсан үе өнгөрсөн. Цаг хугацаа зогсохгүй. Технологийн шинэхэн бизнес эрхлэгч бүр дараагийн Facebook-ийг бий болгохыг хүсдэг бөгөөд үүний зэрэгцээ гартаа авах боломжтой бүх мэдээллийг цуглуулахыг хичээдэг. Бизнесүүдэд мөнгө олоход нь туслах загваруудыг илүү сайн сургахад энэ өгөгдөл хэрэгтэй. Ийм нөхцөлд програмистууд асар их хэмжээний мэдээлэлтэй хурдан бөгөөд найдвартай ажиллах боломжийг олгодог API-г бий болгох хэрэгтэй.

Хуудаслагдсан асуулгад OFFSET болон LIMIT ашиглахаас зайлсхий

Хэрэв та удаан хугацааны турш программ хангамж эсвэл өгөгдлийн сангийн backends зохион бүтээж байсан бол хуудасчилсан асуулга ажиллуулах код бичсэн байх магадлалтай. Жишээлбэл, иймэрхүү:

SELECT * FROM table_name LIMIT 10 OFFSET 40

Энэ нь ямар байна вэ?

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

Та намайг эсэргүүцмээр байна уу? Та чадна үгүй зарцуулах время. Сул, Shopify-ийг и Mixmax Өнөөдөр миний ярихыг хүссэн арга техникийг тэд аль хэдийн ашиглаж байна.

Хэзээ ч ашиглаж байгаагүй ядаж нэг backend хөгжүүлэгчийг нэрлэ OFFSET и LIMIT хуудасласан асуулга явуулах. MVP (Minimum Viable Product) болон бага хэмжээний өгөгдөл ашигладаг төслүүдэд энэ аргыг хэрэглэхэд тохиромжтой. Энэ нь "зүгээр л ажилладаг" гэж хэлж болно.

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

Өнөөдөр бид хуудасласан асуулгын хөдөлгүүрүүдийн түгээмэл хэрэглэгддэг (маш муу) хэрэгжилттэй холбоотой асуудлууд, ийм асуулга гүйцэтгэх үед хэрхэн өндөр гүйцэтгэлд хүрэх талаар ярилцах болно.

OFFSET болон LIMIT-д юу нь буруу байна вэ?

Өмнө хэлсэнчлэн, OFFSET и LIMIT Тэд их хэмжээний өгөгдөлтэй ажиллах шаардлагагүй төслүүдэд сайн ажилладаг.

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

Энэ асуудал гарч ирэхийн тулд DBMS нь хуудасчилсан асуулга бүр дээр бүрэн хүснэгт скан хийх үр ашиггүй үйлдлийг хийх нөхцөл байдал байх ёстой (оруулах, устгах үйлдлүүд гарч болзошгүй бөгөөд бидэнд хуучирсан өгөгдөл хэрэггүй!).

"Бүтэн хүснэгт скан" (эсвэл "дараалсан хүснэгт скан", дараалсан скан) гэж юу вэ? Энэ нь DBMS нь хүснэгтийн мөр бүрийг, өөрөөр хэлбэл түүнд агуулагдах өгөгдлийг дараалан уншиж, өгөгдсөн нөхцөлтэй нийцэж байгаа эсэхийг шалгадаг үйлдэл юм. Энэ төрлийн хүснэгтийг сканнердах нь хамгийн удаан байдаг. Баримт нь үүнийг гүйцэтгэх үед серверийн дискний дэд системтэй холбоотой олон оролт/гаралтын үйлдлүүд хийгддэг. Дискэнд хадгалагдсан өгөгдөлтэй ажиллахтай холбоотой хоцрогдол, дискнээс санах ой руу өгөгдөл дамжуулах нь нөөц их шаарддаг ажил учраас нөхцөл байдлыг улам дордуулж байна.

Жишээлбэл, та 100000000 хэрэглэгчийн бүртгэлтэй бөгөөд та бүтэцтэй асуулга ажиллуулдаг. OFFSET 50000000. Энэ нь DBMS нь эдгээр бүх бичлэгийг ачаалах (мөн бидэнд хэрэггүй!), тэдгээрийг санах ойд оруулах, дараа нь 20 үр дүнг авах шаардлагатай гэсэн үг юм. LIMIT.

Энэ нь иймэрхүү харагдаж магадгүй гэж бодъё: "50000-аас 50020-аас 100000 хүртэлх мөрүүдийг сонго". Өөрөөр хэлбэл, асуулга дуусгахын тулд систем эхлээд 50000 мөрийг ачаалах шаардлагатай болно. Тэр ямар их шаардлагагүй ажил хийх ёстойг харж байна уу?

Хэрэв та надад итгэхгүй байгаа бол функцуудыг ашиглан миний бүтээсэн жишээг харна уу db-fiddle.com

Хуудаслагдсан асуулгад OFFSET болон LIMIT ашиглахаас зайлсхий
Жишээ нь db-fiddle.com

Тэнд, зүүн талд, талбайд Schema SQL, мэдээллийн санд 100000 мөр оруулах код байдаг ба баруун талд талбарт Query SQL, хоёр асуулга харагдаж байна. Эхний удаашрал нь дараах байдалтай байна.

SELECT *
FROM `docs`
LIMIT 10 OFFSET 85000;

Хоёр дахь нь ижил асуудлыг шийдэх үр дүнтэй шийдэл нь дараах байдалтай байна.

SELECT *
FROM `docs`
WHERE id > 85000
LIMIT 10;

Эдгээр хүсэлтийг биелүүлэхийн тулд товчлуур дээр дарахад л хангалттай Run хуудасны дээд талд. Үүнийг хийсний дараа бид асуулга гүйцэтгэх хугацааны талаарх мэдээллийг харьцуулж үздэг. Үр дүнгүй хайлтыг гүйцэтгэх нь хоёр дахь хайлтыг гүйцэтгэхээс дор хаяж 30 дахин их хугацаа шаардагддаг (энэ хугацаа нь гүйлтээс хамаарч өөр өөр байдаг; жишээлбэл, систем эхний хайлтыг гүйцэтгэхэд 37 мс зарцуулсан гэж мэдээлж болно. секунд - 1 мс).

Хэрэв илүү их мэдээлэл байгаа бол бүх зүйл улам дордох болно (үүнд итгэлтэй байхын тулд миний мэдээллийг хараарай. жишээ нь 10 сая мөртэй).

Бидний дөнгөж сая ярилцсан зүйл нь өгөгдлийн сангийн асуулга хэрхэн боловсруулагдаж байгаа талаар тодорхой ойлголт өгөх ёстой.

Утга нь өндөр байх тусмаа гэдгийг анхаарна уу OFFSET - хүсэлтийг дуусгахад удаан хугацаа шаардагдана.

OFFSET болон LIMIT-ийн оронд би юу хэрэглэх ёстой вэ?

Хослолын оронд OFFSET и LIMIT Дараах схемийн дагуу баригдсан бүтцийг ашиглах нь зүйтэй.

SELECT * FROM table_name WHERE id > 10 LIMIT 20

Энэ нь курсор дээр суурилсан хуудаслалттай асуулгын гүйцэтгэл юм.

Орон нутагт одоо байгаа зүйлсийг хадгалахын оронд OFFSET и LIMIT Хүсэлт бүрт тэдгээрийг дамжуулахын тулд та хамгийн сүүлд хүлээн авсан үндсэн түлхүүрийг хадгалах хэрэгтэй (ихэвчлэн энэ нь ID) болон LIMIT, үр дүнд нь дээрхтэй төстэй асуулга авах болно.

Яагаад? Хамгийн гол нь уншсан сүүлчийн мөрийн танигчийг тодорхой зааж өгснөөр та шаардлагатай өгөгдлийг хаанаас хайж эхлэх хэрэгтэйг DBMS-дээ хэлэх болно. Нэмж дурдахад, түлхүүрийг ашигласнаар хайлт үр дүнтэй явагдах бөгөөд систем нь тогтоосон хязгаараас гадуур шугаманд сатаарах шаардлагагүй болно.

Төрөл бүрийн асуулгын дараах гүйцэтгэлийн харьцуулалтыг харцгаая. Энд үр дүнгүй асуулт байна.

Хуудаслагдсан асуулгад OFFSET болон LIMIT ашиглахаас зайлсхий
Удаан хүсэлт

Мөн энэ хүсэлтийн оновчтой хувилбарыг энд оруулав.

Хуудаслагдсан асуулгад OFFSET болон LIMIT ашиглахаас зайлсхий
Шуурхай хүсэлт

Хоёр асуулга нь яг ижил хэмжээний өгөгдлийг буцаана. Харин эхнийх нь 12,80 секунд, хоёр дахь нь 0,01 секунд зарцуулагдана. Та ялгааг мэдэрч байна уу?

Боломжит асуудлууд

Санал болгож буй асуулгын аргыг үр дүнтэй ажиллуулахын тулд хүснэгт нь бүхэл тоо тодорхойлогч гэх мэт өвөрмөц, дараалсан индексүүдийг агуулсан багана (эсвэл багана) байх ёстой. Зарим тодорхой тохиолдолд энэ нь мэдээллийн сантай ажиллах хурдыг нэмэгдүүлэхийн тулд ийм асуулга ашиглах амжилтыг тодорхойлж болно.

Мэдээжийн хэрэг, асуулга үүсгэхдээ та хүснэгтүүдийн тодорхой архитектурыг анхаарч үзэх хэрэгтэй бөгөөд одоо байгаа хүснэгтүүд дээр хамгийн сайн ажиллах механизмуудыг сонгох хэрэгтэй. Жишээлбэл, хэрэв та их хэмжээний холбогдох өгөгдөл бүхий асуулгад ажиллах шаардлагатай бол энэ нь танд сонирхолтой санагдаж магадгүй юм энэ нь нийтлэл.

Хэрэв бид үндсэн түлхүүрээ алдах асуудалтай тулгарвал, жишээлбэл, хэрэв бид олон-олон харьцаатай хүснэгттэй бол ашиглах уламжлалт арга OFFSET и LIMIT, бидэнд тохирох нь баталгаатай. Гэхдээ түүний хэрэглээ нь удаашралтай асуулгад хүргэж болзошгүй. Ийм тохиолдолд би зөвхөн хуудасласан асуултуудыг шийдвэрлэхэд шаардлагатай байсан ч автоматаар нэмэгддэг үндсэн түлхүүрийг ашиглахыг зөвлөж байна.

Хэрэв та энэ сэдвийг сонирхож байгаа бол - болгоогтун, болгоогтун и болгоогтун - хэд хэдэн ашигтай материал.

Үр дүн

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

Өгөгдлийн сангийн асуулгад хэрхэн дүн шинжилгээ хийж, оновчтой болгох вэ?

Хуудаслагдсан асуулгад OFFSET болон LIMIT ашиглахаас зайлсхий

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

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