Ta priročnik zajema praktično optimizacijo baze podatkov MySQL / MariaDB na produkcijskih spletnih mestih – konfiguracijo, indekse, poizvedbe in spremljanje. Velja za okolja cPanel / DirectAdmin, VPS in namenske strežnike z aplikacijami Craft CMS, Laravel ali WordPress.
1. Pred kakršnimi koli spremembami preverite trenutno stanje
Ne spreminjajte ničesar, preden si zastavite izhodiščno vrednost. Brez izhodiščne vrednosti ne veste, ali vam je sprememba pomagala ali škodila.
-- osnovni status SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW GLOBAL STATUS LIKE 'Slow_queries'; SHOW GLOBAL STATUS LIKE 'Questions'; SHOW GLOBAL STATUS LIKE 'Uptime'; -- buffer pool hit ratio (InnoDB) SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads'; SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';Razmerje zadetkov v medpomnilniškem bazenu =-- osnovni status SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW GLOBAL STATUS LIKE 'Slow_queries'; SHOW GLOBAL STATUS LIKE 'Questions'; SHOW GLOBAL STATUS LIKE 'Uptime'; -- buffer pool hit ratio (InnoDB) SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads'; SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';
1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) . Cilj je >99%. Pod 95% pomeni premajhen innodb_buffer_pool_size .
2. Ključne nastavitve v my.cnf
Lokacija: /etc/my.cnf ali /etc/mysql/mariadb.conf.d/50-server.cnf . Po spremembi znova zaženite storitev: systemctl restart mariadb .
[mysqld] # InnoDB — glavna pomoć za performanse innodb_buffer_pool_size = 4G # 50-70% RAM-a na dedicated MySQL innodb_log_file_size = 512M innodb_flush_log_at_trx_commit = 2 # brže, uz mali rizik pri crashu innodb_flush_method = O_DIRECT innodb_file_per_table = 1 # Konekcije max_connections = 200 thread_cache_size = 32 table_open_cache = 4000 # Query cache (OBAVEZNO isključiti u MySQL 5.7+, MariaDB 10.3+) query_cache_type = 0 query_cache_size = 0 # Slow query log slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 1 log_queries_not_using_indexes = 0 # 1 samo privremeno, generira puno logova3. Poiščite počasne poizvedbe[mysqld] # InnoDB — glavna pomoć za performanse innodb_buffer_pool_size = 4G # 50-70% RAM-a na dedicated MySQL innodb_log_file_size = 512M innodb_flush_log_at_trx_commit = 2 # brže, uz mali rizik pri crashu innodb_flush_method = O_DIRECT innodb_file_per_table = 1 # Konekcije max_connections = 200 thread_cache_size = 32 table_open_cache = 4000 # Query cache (OBAVEZNO isključiti u MySQL 5.7+, MariaDB 10.3+) query_cache_type = 0 query_cache_size = 0 # Slow query log slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 1 log_queries_not_using_indexes = 0 # 1 samo privremeno, generira puno logova
Po 24–48 urah delovanja počasnega dnevnika analizirajte:
mysqldumpslow -st -t 20 /var/log/mysql/slow.log Ali bolj berljivo z orodjem pt-query-digest (Percona Toolkit):
pt-query-digest /var/log/mysql/slow.log || lessPrvih 5 poizvedb po skupnem času običajno predstavlja 80 % težav.
4. Analizirajte poizvedbo z uporabo funkcije EXPLAIN
EXPLAIN SELECT * FROM entries WHERE sectionId = 12 AND postDate < NOW();Bodite pozorni na:
-
type:ALLpomeni celotno skeniranje tabele – slabo. Cilj jeref,range,const,eq_ref. -
rows: ocenjeno število vrstic, ki jih mora MySQL prebrati. -
Extra:Using filesortinUsing temporaryje draga – pogosto se reši z ujemanjem indeksovORDER BY/GROUP BY.
5. Indeksi – kje in kakšni
- Indeksiraj stolpce v
WHERE,JOIN,ORDER BY,GROUP BY. - Sestavljeni indeks: vrstni red stolpcev se mora ujemati s poizvedbo.
(sectionId, postDate)deluje zaWHERE sectionId = ? AND postDate < ?, ne deluje pa samo zapostDate. - Izogibajte se indeksom na stolpcih z nizko kardinalnostjo (npr. logični stolpci sami po sebi).
- Preveč indeksov upočasni
INSERT/UPDATE. Sledenje neuporabljenim indeksom:
SELECT * FROM sys.schema_unused_indexes; -- MySQL 5.7+6. Tipični antivzorci
- SELECT * v kodi aplikacije – vedno izvleče samo potrebne stolpce.
- N+1 poizvedb – v ORM (Craft, Eloquent) uporablja eagerly loading (
with,.eagerly()). - LIKE '%xxx' — vodilni nadomestni znak onemogoči indeks. Razmislite o FULLTEXT ali ElasticSearch / MeiliSearch.
- ORDER BY RAND() na velikih tabelah – drago. Zamenjajte z naključnim odmikom ali predpomnilnikom.
- Implicitna pretvorba tipov —
WHERE user_id = '123', ko je stolpec INT. Lahko onemogoči indeks.
7. Konfiguracija za CMS-je
Obrtniški CMS
- Aktiviraj predpomnilnik predlog (
{% cache %}) za dele, ki se ne spreminjajo pogosto. -
.envnastaviteCRAFT_RUN_QUEUE_AUTOMATICALLY=falsein zaženite čakalno vrsto prek cron / supervisor, da zahteve HTTP ne čakajo. - Tabela zbiranja smeti (
sessions,queue,revisions) — prekphp craft gc.
Laravel
- Predpomnjenje poizvedb na ravni baze podatkov prek
->remember()ali Redisa (označeni predpomnilnik). -
config:cache,route:cache,view:cachev produkciji. - Octane ali FrankenPHP, ko TTFB postane ozko grlo.
WordPress / WooCommerce
- Predpomnilnik objektov (Redis ali Memcached) – največja razlika.
- Odstranite neuporabljene vtičnike. Vsak od njih doda poizvedbe v
wp_options. - Čiščenje samodejnega nalaganja:
SELECT option_name, LENGTH(option_value) FROM wp_options WHERE autoload='yes' ORDER BY 2 DESC LIMIT 20;
8. Vzdrževanje
# analiziraj i optimiziraj tablice (jednom mjesečno) mysqlcheck --all-databases --analyze mysqlcheck --all-databases --optimize # provjeri veličine tablica SELECT table_name, ROUND(data_length/1024/1024, 1) AS data_mb, ROUND(index_length/1024/1024, 1) AS idx_mb FROM information_schema.tables WHERE table_schema = DATABASE() ORDER BY data_length DESC LIMIT 20;9. Ko je prišel čas za nadgradnjo infrastrukture
Če imate po vsem zgoraj navedenem še vedno težave, je ozko grlo nekje drugje:
- CPU stalno >70 % – manjkajoča jedra, razmislite o vertikalni nadgradnji ali ločitvi spleta/baze podatkov.
- Razmerje zadetkov medpomnilniškega bazena <95 % z največjo količino RAM-a – čas je za večji strežnik ali delitev.
- Čakanje na V/I diska >10 % – nadgradnja NVMe ali ločevanje dnevnikov od podatkovne mape.
10. Varnostni napotki
- Nikoli ne preizkušajte novih konfiguracij neposredno v produkciji. Potreben je preizkusni strežnik z enakimi podatki.
- Pred vsako spremembo datoteke
my.cnfkopirajte trenutno datoteko. - V primeru dramatičnih sprememb
innodb_log_file_sizeje treba MySQL pred ponovnim zagonom pravilno zaustaviti, ker morajo biti stare datoteke dnevnika čiste.
Ko se zatakne ali ni jasno, kaj spremeniti, se obrnite na podporo – imamo dnevnike dostopov, dnevnike počasnih poizvedb in podatke spremljanja za vsak strežnik, ki ga gostimo, in vam lahko pokažemo, kje je težava.