Bu gün baxacağıq ki, PostgreSQL-in icra planındakı node-lar nədir, onları necə oxumaq lazımdır və ən əsası, nəyinsə səhv getdiyini necə başa düşmək olar. Sən öyrənəcəksən ki, niyə sənin database bəzən resurs yeyən Seq Scan-ı seçir, halbuki artıq index var, bəlkə də bir neçə dənə.
PostgreSQL sorğunun icra planını quranda onu mərhələlərə bölür, bunlara node deyilir. Hər bir node — database serverinin sənin sorğunu işlətmək üçün etdiyi bir "addım"dır. Əsas node tiplərinə daxildir:
Sequential Scan (Seq Scan)
Seq Scan və ya ardıcıl skan — cədvəldən məlumat çıxarmağın ən sadə yoludur. PostgreSQL sadəcə cədvəli götürür, sətirləri bir-bir oxuyur və yoxlayır ki, onlar sənin sorğunun şərtlərinə uyğundurmu.
Seq Scan nə vaxt istifadə olunur?
Seq Scan aşağıdakı hallarda tətbiq olunur:
- Cədvəldə sorğunu sürətləndirmək üçün uyğun index yoxdur.
- Filter şərti çox ümumidir, yəni index faydalı olmur (məsələn, 50%-dən çox məlumat çıxarılırsa).
- PostgreSQL hesab edir ki, cədvəli ardıcıl oxumaq index-dən istifadə etməkdən daha sürətlidir (bəzən çox kiçik cədvəllərdə belə olur).
EXPLAIN SELECT * FROM students WHERE age > 18;
Nümunə nəticə:
Seq Scan on students (cost=0.00..35.50 rows=10 width=50)
Filter: (age > 18)
Seq Scan on students-ə fikir ver — bu o deməkdir ki, PostgreSQL "students" cədvəlini tam oxuyacaq.
Seq Scan problemləri: Əgər cədvəl böyükdürsə, ardıcıl skan çox vaxt apara bilər.
Index Scan
Index Scan — məlumatı index vasitəsilə oxumaqdır. PostgreSQL-də index yaradanda, bu sanki cədvəlin "mündəricatını" düzəltmək kimidir. Əgər sorğu index-dən istifadə edə bilirsə, PostgreSQL cədvəli tam oxumur, yalnız lazım olan hissələri götürür.
Index Scan nə vaxt istifadə olunur?
- Sorğuda index olan sütun üçün filter şərti var (məsələn,
WHERE). =,<,>,BETWEENvə s. kimi müqayisə əməliyyatları istifadə olunur.
CREATE INDEX idx_students_age ON students(age);
EXPLAIN SELECT * FROM students WHERE age = 18;
Nümunə nəticə:
Index Scan using idx_students_age on students (cost=0.15..8.27 rows=1 width=50)
Index Cond: (age = 18)
Burada Index Scan using idx_students_age göstərir ki, PostgreSQL idx_students_age index-dən istifadə edir. Sətir-sətir cədvəl oxumaq əvəzinə, index vasitəsilə daha sürətli giriş olur.
Index Scan üstünlükləri:
- Böyük cədvəllərdə sorğuların sürətini xeyli artırır.
- Diskdən oxunan məlumatın miqdarını azaldır.
Index Scan problemləri:
Əgər sorğun çoxlu məlumat qaytarırsa (məsələn, cədvəlin yarısından çoxunu), index-dən istifadə bəzən Seq Scan-dan da yavaş ola bilər.
Hash Join
Hash Join iki cədvəli join şərti əsasında birləşdirmək üçün istifadə olunur (məsələn, ON students.course_id = courses.id). PostgreSQL cədvəllərdən birinin (adətən kiçik olanın) hash cədvəlini yaradır və digər cədvəldə uyğunluqları tapmaq üçün ondan istifadə edir.
Hash Join nə vaxt istifadə olunur?
- Cədvəllər
INNER JOIN,LEFT JOINvə s. ilə birləşdiriləndə. - PostgreSQL hesab edir ki,
Hash Joindigər join metodlarından daha effektivdir.
EXPLAIN
SELECT *
FROM students
JOIN courses ON students.course_id = courses.id;
Nümunə nəticə:
Hash Join (cost=25.00..50.00 rows=10 width=100)
Hash Cond: (students.course_id = courses.id)
-> Seq Scan on students (cost=0.00..20.00 rows=10 width=50)
-> Hash (cost=15.00..15.00 rows=10 width=50)
-> Seq Scan on courses (cost=0.00..15.00 rows=10 width=50)
Burada Hash Join iki cədvəli birləşdirir. Fikir ver ki, PostgreSQL əvvəlcə hər iki cədvəl üçün Seq Scan edir, sonra isə hash cədvəli (Hash) qurur.
Hash Join üstünlükləri:
- Orta ölçülü cədvəllər üçün sürətli işləyir.
- Çoxlu sətir olan cədvəlləri birləşdirmək üçün effektivdir.
Hash Join problemləri:
Əgər hash cədvəlinin ölçüsü mövcud yaddaşı aşırsa, PostgreSQL onu diskdə saxlayacaq və bu da join-i xeyli yavaşladır.
İcra planının təhlili nümunəsi
Gəlin real bir nümunəyə baxaq.
Sorğu:
EXPLAIN ANALYZE
SELECT *
FROM students
JOIN courses ON students.course_id = courses.id
WHERE students.age > 18;
Nəticə:
Hash Join (cost=35.00..75.00 rows=5 width=100) (actual time=1.00..2.50 rows=5 loops=1)
Hash Cond: (students.course_id = courses.id)
-> Seq Scan on students (cost=0.00..40.00 rows=10 width=50) (actual time=0.50..1.00 rows=7 loops=1)
Filter: (age > 18)
Rows Removed by Filter: 3
-> Hash (cost=25.00..25.00 rows=5 width=50) (actual time=0.30..0.30 rows=5 loops=1)
-> Seq Scan on courses (cost=0.00..20.00 rows=5 width=50) (actual time=0.20..0.25 rows=5 loops=1)
Planning Time: 0.50 ms
Execution Time: 3.00 ms
Interpretasiya:
Hash Join: Əsas node. PostgreSQLstudentsvəcoursescədvəllərini birləşdirir.actual time: 1.00-dan 2.50 ms-ə qədər.rows=5: sorğu 5 sətir qaytardı.
- Daxili node-lar:
Seq Scan on students:studentscədvəlini ardıcıl oxuyur və(age > 18)filtrini tətbiq edir.Rows Removed by Filter = 3: 3 sətir şərtə uyğun gəlmədi.Hash: PostgreSQLcoursescədvəli üçün hash cədvəli yaradır.
Node-ların müqayisəsi və seçimi
İcra planını təhlil edəndə əsas məsələ odur ki, PostgreSQL-in niyə məhz bu və ya digər məlumat işləmə metodunu seçdiyini başa düşəsən. Bəzən müdaxilə etmək lazım olur, məsələn, index əlavə etmək və ya sorğunu dəyişmək. Bir neçə məsləhət:
- Böyük cədvəldə
Seq Scangörürsənsə, index barədə düşün. Hash Joinçox yavaşdırsa, PostgreSQL üçün mövcud yaddaşı yoxla.EXPLAIN ANALYZEistifadə et ki, proqnozlaşdırılan və real metrikləri (rows,time) müqayisə edəsən.
Bu mərhələdə artıq sorğuların icra planlarını oxumaq və onların node-larını interpretasiya etmək barədə əsas anlayışa maliksən. Növbəti dərslərdə optimizasiya problemləri və onların həlli barədə danışacağıq.
GO TO FULL VERSION