Niyə anahtarlarda paginasiya dəstəyi lazımdır?

Hər kəsə salam! Mən arxa tərəf inkişaf etdiricisiyəm, Java + Spring ilə mikroservislər yazıram. Tinkoff şirkətində daxili məhsulları inkişaf etdirən komandaların birində çalışıram.

Niyə anahtarlarda paginasiya dəstəyi lazımdır?

Komandamızda tez-tez verilənlər bazası sorğularının optimallaşdırılması sualı ortaya çıxır. Həmişə bir az daha sürətli olmağı istəyirik, lakin həmişə düşünülmüş şəkildə yaradılmış indekslərlə kifayətlənmək mümkün olmur — bəzən alternativ yollar axtarmağa məcbur oluruq. Verilənlər bazası ilə işləmək üçün düşünülmüş optimizasiyalar axtararkən, qarşıma çıxan sonsuz dərəcədə faydalı Markus Winandın bloqudur,SQL Performance Explained kitabının müəllifidir. Bu, bütün məqalələri ardıcıl oxumaq olar, çox nadir bir blog növüdür.

Sizin üçün Markusun kiçik bir məqaləsini tərcümə etmək istəyirəm. Onu müəyyən mənada bir manifest olaraq adlandırmaq olar ki, SQL standartına görə offset əməliyyatının performansına diqqət çəkmək məqsədini güdür.

Bəzi yerlərdə müəllifi əlavə izahlarla və şərhlərlə tamamlayacağam. Belə yerləri daha aydın olması üçün «pr.m» işarəsi ilə göstərəcəm.

Kiçik bir giriş

Düşünürəm ki, bir çoxları bilirlər ki, offset vasitəsilə səhifələmə seçkiləri ilə işləmək nə qədər problemli və ləng olur. Ancaq bilirsinizmi ki, bunu daha səmərəli bir qurğu ilə əvəz etmək mümkündür?

Beləliklə, offset açar sözü verilənlər bazasına sorğuda ilk n qeydləri atlamağı bildirir. Lakin verilənlər bazası hələ də bu ilk n qeydləri diskdən oxumalıdır, üstəlik təyin olunmuş sıraya (pr.: əgər sıralama varsa, onu tətbiq edin) uyğun olaraq və yalnız bundan sonra n+1 və daha sonrası qeydləri qaytarmaq mümkün olacaq. Maraqlısı odur ki, problem spesifik verilənlər bazası reallaşdırmasında deyil, standartın başlanğıc müəyyən edilməsindədir:

…sətirlər əvvəlcə görə sıralanır və sonra tərəfindən göstərilən sətirlərin sayını atlayaraq məhdudlaşdırılır…
-SQL:2016, Part 2, 4.15.3 Derived tables (pr.: indi ən çox istifadə olunan standart)

Buradakı əsas məqam odur ki, offset yalnız bir parametr - atlanılacaq qeydlərin sayını qəbul edir. Bu tərifə əsasən, verilənlər bazası yalnız bütün qeydləri çıxarıb, sonra lazımsız olanları atmağa məcburdur. Aydındır ki, belə bir offset tərifi əlavə iş görməyə vadar edir. Burada SQL və ya NoSQL olmasının fərqi yoxdur.

Bir az daha ağrı

Offset problemləri bununla bitmir və buna görədir. Diskdən iki məlumat səhifəsini oxuyarkən, başqa bir əməliyyat yeni bir qeyd daxil etsə, bu halda nə baş verir?

Niyə anahtarlarda paginasiya dəstəyi lazımdır?

Əgər offset istifadə edilərək əvvəlki səhifələrdən qeydlər atlanırsa, fərqli səhifələr arasında oxuma əməliyyatları zamanı yeni bir qeyd əlavə edilsə, çox güman ki, siz duplicat əldə edəcəksiniz (pr.: bu, order by qurğusunu istifadə edəndə mümkündür, belə olduqda yeni qeyd bizim nəticələrimizin ortasına düşə bilər).

Cədvəl bu situasiyanı açıq şəkildə təsvir edir. Verilənlər bazası ilk 10 qeydi oxuyur, sonra yeni bir qeyd daxil edilir ki, bu da bütün oxunan qeydləri 1 ilə irəliləyir. Sonra baza 10 növbəti qeydi götürür və 11-ci qeyddən başlamalı olduğu halda 10-cu qeyddən başlayır, bu qeyd iki dəfə alınır. Bu ifadənin istifadəsi ilə bağlı başqa anomaliyalar da var, lakin bu - ən yayğın olanıdır.

Artıq bildiyimiz kimi, bu, konkret DBMS-lərin və ya onların icrası ilə bağlı problemlər deyil. Problem - SQL standartına uyğun səhifələməni müəyyənləşdirməkdədir. Biz DBMS-ə hansı səhifəni götürmək lazım olduğunu və ya nə qədər qeyd atlamaq lazım olduğunu deyirik. Baza bu cür sorğunu optimallaşdırmaqda çətinlik çəkir, çünki bunun üçün çox az məlumat var.

Eyni zamanda, bunun konkret bir açar söz problemi olmadığını, daha çox sorğunun semantikası ilə bağlı olduğunu qeyd etmək vacibdir. Problemlə eyni olan bir neçə identik sintaksis var:

  • Daha əvvəl qeyd edildiyi kimi, offset açar sözü.
  • Limit [offset] açar sözlərindən ibarət quruluş (hər nə qədər limit özü pis deyil).
  • İntervalın alt sərhədləri üzrə filtrasiya (məsələn, row_number(), rownum və s.).

Bütün bu ifadələr sadəcə neçə sətiri atlamağı bildirir, əlavə bir məlumat və ya kontekst yoxdur.

Məqalənin davamında offset açar sözü bu variantların hamısını ümumiləşdirmək üçün istifadə olunur.

OFFSET olmadan həyat

İndi təsəvvür edin ki, bizim dünyamız bu problemlər olmadan necə olardı. Məlum olur ki, offset olmadan həyat elə də çətin deyil: yalnız əvvəllər görmədiyimiz sətirləri (yəni, əvvəlki səhifədə olmayanları) seçmək üçün şərti where hissəsində istifadə edə bilərik.

Bu halda, seçkilərin sıralanmış çoxluq üzərində icra edildiyini nəzərə alırıq (köhnə yaxşı order by). Sıralanmış bir çoxluğumuz olduğuna görə, yalnız əvvəlki səhifənin son qeydindən sonrakı məlumatları əldə etmək üçün olduqca sadə bir filtri istifadə edə bilərik:

    SELECT ...
    FROM ...
    WHERE ...
    AND id < ?last_seen_id
    ORDER BY id DESC
    FETCH FIRST 10 ROWS ONLY

Budur, bu yanaşmanın prinsipi. Əlbəttə, bir çox sütun üzrə sıralananda işlər daha maraqlı olur, lakin əsas ideya eynidir. Vacibdir ki, bu quruluş bir çox NoSQhətta-həllərdə tətbiq oluna bilər.

Belə yanaşma seek metodu və ya keyset səhifələmə adlanır. Bu, oxu səhifələri arasında meydana gələn sürüşən nəticə problemini (yəni, əvvəllər təsvir edilən qeydlə bağlı vəziyyət) həll edir və əlbəttə ki, biz hamımızın sevdiyi kimi, klassik offset-dən daha sürətli və stabil işləyir. Stabilite, sorğunun icra müddətinin soruşulan cədvəl nömrəsinə mütənasib olaraq artırılmamasındadır (məsələn, səhifələmə yanaşmaları haqqında daha ətraflı öyrənmək istəyirsinizsə, müəllifin təqdimatını açın. Orada müxtəlif metodlarla bağlı müqayisəli benchmarklar da tapa bilərsiniz.

Bir slayd danı izah edir, açarlar üzrə səhifələmənin, əlbəttə ki, hər şeyə qadir olmadığı — öz məhdudiyyətləri var. Ən vacib məhdudiyyət isə odur ki, təsadüfi səhifələri oxumaq imkanı yoxdur (qeyd: ardıcıllıqla deyil). Lakin sonsuz sürüşmə dövründə (qeyd: frontend-də) bu, o qədər də problem deyil. Səhifə nömrəsi göstərişi — UI inkişafı üçün, belə və ya belə, pis bir həlldir (qeyd: məqalənin müəllifinin fikri).

Bəs alətlər nə ilə bağlıdır?

Açarlar üzrə səhifələmə, adətən, bu metodun alət dəstəyi olmadığı üçün uyğunsuzdur. İnkşaf alətlərinin əksəriyyəti, o cümlədən müxtəlif çərçivələr, səhifələmənin hansı şəkildə həyata keçiriləcəyini seçmək imkanı vermir.

Vəziyyəti ağırlaşdıran odur ki, təsvir olunan metod, istifadə olunan texnologiyalarda — DBM-dən başlayaraq AJAX sorğularının brauzerdə sonsuz sürüşmə zamanı icrasına qədər — tam dəstək tələb edir. İndi yalnız səhifə nömrəsini göstərmək əvəzinə, bütün səhifələr üçün açar dəstini göstərməli olacaqsınız.

Amma açarlar üzrə səhifələməni dəstəkləyən çərçivələrin sayı tədricən artır. Hazırda olanlar bunlardır:

(Qeyd: bəzi bağlantılar 2017-2018-ci ildən bəri yenilənmədiyi üçün silinmişdir. Maraqlıdırsa, orijinal mənbəyə baxa bilərsiniz.)

Məhz bu məqama sizin köməyiniz lazımdır. Əgər siz açarlar üzrə səhifələmə istifadə edən və ya dəstəkləyən bir çərçivə inkişaf etdirirsinizsə, xahiş edirəm, sizə, sizin üçün bu, kömək edəcək, mən sizə, sizlərin açarlar üzrə səhifələmə üçün nativ dəstək etməyə çağırıram. Suallarınız varsa və ya köməyə ehtiyacınız varsa, yardım etməyə məmnun olaram (forum, Twitter, müraciət forması) (qeyd: Markusla olan təcrübəmdən, bu mövzunun yayılmasına həqiqətən həyəcanlandığını deyə bilərəm).

Əgər siz isə, açarlar üzrə səhifələmə dəstəyi almağa layiq olduğunu düşündüyünüz hazır həllərdən istifadə edirsinizsə, xahiş edirəm bir sorğu yaradın və ya mümkün olduğu halda hazır bir həlli təklif edin. Həmçinin bu məqaləni bağlantı vasitəsilə qeyd edə bilərsiniz.

Nəticə

Belə sadə və faydalı bir yanaşmanın, açarlar üzrə səhifələmə, yayılmamasının səbəbi, bunun texniki icrasının çətin olması və ya böyük səylər tələb etməsindən deyil. Əsas səbəb, bir çoxunun offset ilə işləməyə alışmış olmasıdır — belə bir yanaşma, özü standart tərəfindən diktə edilir.

Nəticə olaraq, az sayda insan səhifələməyə yanaşmanın dəyişməsi barədə düşünür, buna görə də çərçivələr və kitabxanalar tərəfindən alət dəstəyi zəif inkişaf edir. Buna görə də, əgər siz ofsetsiz səhifələməni yaxın bir fikir və məqsəd kimi qəbul edirsinizsə, onun yayılmasına kömək edin!

Mənbə: https://use-the-index-luke.com/no-offset
Müəllif: Markus Winand

Mənbə: habr.com

DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər 🔥 DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər | ProHoster