Slow Query Log — sekin so'rovlarni topish
Muammodan boshlaylik
Foydalanuvchilar shikoyat qiladi: "Sayt ba'zan sekin ishlaydi". Qaysi sahifa? Qaysi so'rov? Ilovada yuzlab turli SQL so'rov bor. EXPLAIN ni hammasiga birma-bir qo'llash — bir hafta ish.
Avval qaysi so'rovlar sekin ekanini aniqlash kerak. MySQL buni o'zi yozib boradi — slow query log ga.
Yoqish
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 1 soniyadan uzoq so'rovlar
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
Server qayta ishga tushganda ham saqlanishi uchun — konfiguratsiya faylida (my.cnf / my.ini):
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
| Sozlama | Ma'nosi |
|---|---|
long_query_time |
Shu soniyadan uzoq so'rovlar yoziladi (kasr ham mumkin: 0.5) |
log_queries_not_using_indexes |
Indekssiz so'rovlar — tez bo'lsa ham (kichik jadvallar ham tushadi — shovqinli) |
min_examined_row_limit |
Kamida shuncha qator o'qigan so'rovlar |
[!TIP] Boshida
long_query_time = 1bilan boshlang. Asosiy muammolar tuzatilgach —0.5, keyin0.1ga tushiring.0— barcha so'rovlar yoziladi: tahlil uchun qisqa muddatga foydali, lekin disk tez to'ladi.
Log fayl ichida nima bor
# Time: 2026-11-04T10:15:32.123456Z
# User@Host: dokon_app[dokon_app] @ localhost [] Id: 847
# Query_time: 3.482115 Lock_time: 0.000102 Rows_sent: 20 Rows_examined: 4800000
SET timestamp=1793787332;
SELECT id, yaratilgan FROM buyurtmalar WHERE holat = 'yangi' ORDER BY yaratilgan DESC LIMIT 20;
| Maydon | Ma'nosi |
|---|---|
Query_time |
So'rov qancha davom etdi |
Lock_time |
Qulfni kutish vaqti |
Rows_sent |
Mijozga qaytarilgan qatorlar |
Rows_examined |
O'qilgan qatorlar |
Eng muhim signal — Rows_examined va Rows_sent nisbati. 20 ta qator uchun 4.8 million o'qilgan — indeks yo'q yoki noto'g'ri.
mysqldumpslow — umumlashtirish
Log faylda minglab yozuv bo'ladi. Bir xil so'rov turli qiymatlar bilan yuzlab marta takrorlanadi. mysqldumpslow ularni guruhlaydi:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
-s t— umumiy vaqt bo'yicha saralash (c— soni,at— o'rtacha vaqt)-t 10— top 10
Count: 1840 Time=2.91s (5354s) Lock=0.00s (0s) Rows=20.0 (36800)
SELECT id, yaratilgan FROM buyurtmalar WHERE holat = 'S' ORDER BY yaratilgan DESC LIMIT N
Count: 12 Time=8.40s (100s) Lock=0.00s (0s) Rows=1.0 (12)
SELECT COUNT(*) FROM mijozlar m JOIN ...
Qiymatlar 'S' (string) va N (son) bilan almashtirilgan — bir xil shakldagi so'rovlar bitta guruhga.
Muhim: birinchi so'rov bittasi 2.9 soniya, lekin 1840 marta — jami 89 daqiqa. Ikkinchisi 8.4 soniya, lekin atigi 12 marta. Birinchisini tuzatish ancha foydali. Umumiy vaqt bo'yicha saralang, bitta so'rov vaqti bo'yicha emas.
Kuchliroq vosita — pt-query-digest (Percona Toolkit): batafsil statistika, foizlar, taqsimot.
Performance Schema — log siz
MySQL 8 da log faylsiz ham statistika to'planadi:
SELECT
DIGEST_TEXT AS sorov,
COUNT_STAR AS soni,
ROUND(SUM_TIMER_WAIT / 1e12, 2) AS jami_soniya,
ROUND(AVG_TIMER_WAIT / 1e12, 3) AS ortacha_soniya,
SUM_ROWS_EXAMINED AS oqilgan_qatorlar,
SUM_NO_INDEX_USED AS indekssiz
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
Yoki tayyor ko'rinish (sys sxemasi):
SELECT * FROM sys.statements_with_full_table_scans LIMIT 10;
SELECT * FROM sys.statement_analysis LIMIT 10;
Ishlatilmayotgan indekslar (o'chirish uchun nomzodlar):
SELECT * FROM sys.schema_unused_indexes WHERE object_schema = 'dokon';
[!INFO] Bu statistika server qayta ishga tushirilgandan beri to'planadi. Yangi ishga tushirilgan serverda "ishlatilmagan" indeks haqiqatan ham keraksiz bo'lmasligi mumkin — oylik hisobot uchun ishlatiladigan indeks bir oy jim turadi.
Hozir nima bajarilyapti?
Sayt "osilib" qoldi — aynan hozir nima bo'lyapti?
SHOW FULL PROCESSLIST;
+-----+-----------+-----------+-------+---------+------+--------------+---------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+-----------+-----------+-------+---------+------+--------------+---------------------------+
| 847 | dokon_app | localhost | dokon | Query | 142 | Sending data | SELECT ... FROM buyurtma..|
| 851 | dokon_app | localhost | dokon | Query | 138 | Waiting for | UPDATE mahsulotlar ... |
| | | | | | | table lock | |
+-----+-----------+-----------+-------+---------+------+--------------+---------------------------+
Time — necha soniyadan beri bajarilyapti. 142 soniyalik so'rov boshqa so'rovlarni bloklab turgan bo'lishi mumkin.
To'xtatish:
KILL QUERY 847; -- faqat so'rovni
KILL 847; -- butun ulanishni
Ilova darajasida
Baza logidan tashqari, ilovada ham so'rovlarni kuzatish foydali:
- Laravel — Telescope, Debugbar: har bir sahifada qanday so'rovlar va qancha vaqt
- Node.js — ORM loglari (
logging: true) - APM vositalari — New Relic, Datadog, Sentry Performance
Ular "qaysi sahifa sekin va unda nechta so'rov" ni ko'rsatadi — N+1 muammosini (18-dars) aynan shu yerda ko'rasiz: bitta sahifada 300 ta bir xil so'rov.
Nima uchun shunday?
Nima uchun sekin so'rovlarni oldindan, kod yozayotganda topib bo'lmaydi?
Chunki tezlik ma'lumotga bog'liq. Dasturchi kompyuterida 100 ta buyurtma — har qanday so'rov bir zumda. Production da 5 million — va ba'zi so'rovlar birdan minglab marta sekinlashadi. Bundan tashqari, real foydalanuvchilar siz kutmagan filtrlar va kombinatsiyalarni ishlatadi. Shuning uchun optimizatsiya — kuzatish bilan boshlanadi: avval o'lchang, keyin tuzating. Slow query log — o'lchash vositasi.
Xulosa
Eslab qoling:
slow_query_log = ON,long_query_time = 1— sekin so'rovlarni yozish- Logda:
Query_time,Rows_examinedvsRows_sent— asosiy signal mysqldumpslow -s t— umumiy vaqt bo'yicha top so'rovlar- Tez-tez bajariladigan "o'rtacha sekin" so'rov — ko'pincha eng katta muammo
performance_schema/sys— logsiz statistika, ishlatilmagan indekslarSHOW FULL PROCESSLIST+KILL QUERY— hozirgi muammolar- Avval o'lchang, keyin optimizatsiya qiling
Keyingi dars
34-dars: Query optimizatsiya — N+1, covering index, qoidalar