Portál AbcLinuxu, 10. května 2025 12:02

Dotaz: mysql tuning

1.12.2012 20:18 nun
mysql tuning
Přečteno: 1859×
Odpovědět | Admin
Zdravím,

na 2 malé weby (každý po 10mb databázi) s cca 1k uip dohromady jsem si pořídil virtuál se 4gb od wedosu. Tzn. silně naddimenzováno.

Reálně je využito dle top 1gb, další 3gb jsou free, 3 vlákna procesoru se nudí k smrti :-)

Vzhledem k úmyslnému přebytku paměti ram, mám vytvořený tmpfs ramdisk, kde jsou naházeny sessions a mysql tmp dir (samozřejmě php-apc.stat, memcached) je taky v provozu, innodb vyřazeno, jede to na myisam vše.

Ale stejně se mi nelíbí, že se občas stránka loaduje 0,3s. Prosím, můžete mrknout, jestli vám tam nepřijde něco co by se dalo ještě vylepšit? Vím že tam mám nějakou vyšší rezervu pro cache a indexy, ale to nevadí, vzhledem k velkému přebytku ram.
[client]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock


[mysqld_safe]
socket		= /var/run/mysqld/mysqld.sock
nice		= 0

[mysqld]
#
# * Basic Settings
#
log_slow_queries = ON
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 4
user		= mysql
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
port		= 3306
basedir		= /usr
datadir		= /var/lib/mysql
tmpdir		= /mnt/tmpfs/mysql
language	= /usr/share/mysql/english
skip-external-locking
skip-locking
skip-innodb
skip-federated
ft_min_word_len = 2
#
# Instead of skip-networking the default is now to listen only on  
# localhost which is more compatible and is not less secure.
#bind-address		= 127.0.0.1
#
# * Fine Tuning
#
key_buffer		= 192M
key_buffer_size		= 192M
max_allowed_packet	= 16M
thread_stack		= 192K
thread_cache_size       = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover         = BACKUP
max_connections        = 100
table_cache            = 1k
#table_open_cache = 600
#thread_concurrency     = 10
thread_concurrency = 6
#
# * Query Cache Configuration
#
query_cache_limit	= 16M
query_cache_size        = 128M
expire_logs_days	= 10
max_binlog_size         = 100M
#binlog_do_db		= include_database_name
#binlog_ignore_db	= include_database_name
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem



[mysqldump]
quick
quote-names
max_allowed_packet	= 16M

[mysql]
#no-auto-rehash	# faster start of mysql but no tab completition

[isamchk]
key_buffer		= 16M

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/
Něco z tuneru (jede to chvilku, takže ty read/write ještě trochu zefektivní):
[OK] Maximum possible memory usage: 604.7M (15% of installed RAM)
[OK] Slow queries: 0% (0/3K)
[OK] Highest usage of available connections: 2% (2/100)
[OK] Key buffer size / total MyISAM indexes: 192.0M/8.6M
[!!] Key buffer hit rate: 65.9% (21K cached / 7K reads)
[OK] Query cache efficiency: 43.9% (1K cached / 2K selects)
[OK] Query cache prunes per day: 0
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 150 sorts)
[OK] Temporary tables created on disk: 19% (142 on disk / 739 total)
[OK] Thread cache hit rate: 99% (2 created / 372 connections)
[OK] Table cache hit rate: 20% (88 open / 432 opened)
[OK] Open file limit used: 7% (152/2K)
[OK] Table locks acquired immediately: 100% (1K immediate / 1K locks)
Díky moc!
Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

1.12.2012 20:41 Kit
Rozbalit Rozbalit vše Re: mysql tuning
Odpovědět | | Sbalit | Link | Blokovat | Admin
Obvykle nejlépe pomáhá tuning SQL dotazů. Těch 0,3 s je doba zpracování SQL dotazu nebo doba běhu skriptu?
1.12.2012 23:32 Marek
Rozbalit Rozbalit vše Re: mysql tuning
Odpovědět | | Sbalit | Link | Blokovat | Admin
Pokud nevíte, jak je těch 0.3s rozloženo, co skutečně bere čas, pak jakákoliv optimalizace naslepo nedává smysl. Začal bych profilováním běhu a tím pádem i nalezením úzkého hrdla.
AsciiWolf avatar 19.12.2012 12:38 AsciiWolf | skóre: 41 | blog: Blog
Rozbalit Rozbalit vše Re: mysql tuning
+1
3.12.2012 00:32 nun
Rozbalit Rozbalit vše Re: mysql tuning
Odpovědět | | Sbalit | Link | Blokovat | Admin
ještě se zeptám, tuner mi doporučuje používat LIMIT...

když používám

SELECT * FROM tbl WHERE id=400000

má smysl použít LIMIT 1? (id je unikátní, primary)

Logicky mi to přijde zbytečné, co na to vy? Díky.

A ještě otázka: Mám

tmp_table_size = 128M max_heap_table_size=128M

a jak jsem psal, mám 2 databáze, každá s cca 20 tabulkami, s tím, že celá databáze má kolem 10-20 MB. A přesto je docela velké číslo dočasných tabulek. Jak to lze napravit?

Díky.

3.12.2012 06:24 Kit
Rozbalit Rozbalit vše Re: mysql tuning
Určitě bych se nesnažil optimalizovat takové primitivní dotazy a soustředil bych se na komplexní, ve kterých je použito spojování tabulek. Také bych se pokusil snížit počet dotazů na jednotky pro zobrazení jedné webové stránky. Volání SQL dotazu v cyklu bývá velmi častá chyba.

Také bývají chybou velmi dlouhé skripty, někdy i desítky tisíc řádek (po zpracování všech includů). Kompilace také zabere nějaký čas. Důležité je includovat jen skripty, které jsou pro běh skutečně nutné.
3.12.2012 19:28 nun
Rozbalit Rozbalit vše Re: mysql tuning
joiny vůbec nepoužívám. teď mě napadá, často používám:
$d=mysql_query("SELECT ... FROM tbl ORDER BY id DESC LIMIT 40");
while($a=mysql_fetch_array($d)) {
// echo řádek v tabulce
}
Jak čtu, je to chyba? Bylo by efektivnější jako třeba:

for($i=0;$i<40;$i++) { $a=mysql_fetch_array(mysql_query("SELECT ... FROM tbl ORDER BY id DESC LIMIT $i,1"); // echo řádek v tabulce }

?

Co se týče dlouhých skriptů nebo tak to mám v pořádku, jen nějaké SQL dotazy bude potřeba vyladit (viz výše).

Díky.
3.12.2012 19:54 Kit
Rozbalit Rozbalit vše Re: mysql tuning
Ten první cyklus je v pořádku. Ten druhý příklad je naopak nevhodný a zdržující. Operátory JOIN je často výhodné nahradit operátorem IN.

Častou chybou bývá načtení cizích klíčů z jedné tabulky do pole a pro každou položku pole volání dalšího SELECTu do jiné tabulky. Pokud nepoužíváš operátory JOIN ani IN a máš normalizovanou databázi, je velmi pravděpodobné, že se této chyby dopouštíš.
3.12.2012 20:20 nun
Rozbalit Rozbalit vše Re: mysql tuning
To máš pravdu, s tím voláním dalších selectů do jiných tabulek - ale myslím si, že to jsou takové primitivní dotazy u kterých to je nula nula nic.

Mě spíš děsí, následující update dotaz. Logicky by to měl být ten nejsnadnější a nejrychlejší update, ale opak je pravdou - prakticky co loguji slow queryes vlastní aplikací (loguji už 0,3s), mserverové SQ až od 4s. Nicméně, tedy, mám tabulku (má cca 300 záznamů) :
CREATE TABLE IF NOT EXISTS adm_st (
  id int(11) NOT NULL AUTO_INCREMENT,
  cas varchar(6) COLLATE utf8_czech_ci NOT NULL,
  acc int(11) NOT NULL,
  schvalil int(11) NOT NULL DEFAULT '0',
  zamitl int(11) NOT NULL DEFAULT '0',
  prevzal int(11) NOT NULL DEFAULT '0',
  prac int(11) NOT NULL DEFAULT '0',
  logu int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (id),
  KEY acc (acc),
  KEY cas_2 (cas)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
a občas do ní provádím tyto dotazy:
db_query("UPDATE adm_st SET prac=(prac+$rozdil) WHERE cas='".date("dmy")."' AND acc={$_SESSION[usr][id]}") or die(mysql_error());
tzn.
UPDATE adm_st SET prac=(prac+2) WHERE cas='031212' AND acc=4057;
--- a tento dotaz trvá snad nyní už jen jako jediný tak dlouho a nebere mi, proč tomu tak je.
# Query_time: 8.058708  Lock_time: 0.000069 Rows_sent: 0  Rows_examined: 4
SET timestamp=1354532425;
Ještě jednou díky!
3.12.2012 21:22 Kit
Rozbalit Rozbalit vše Re: mysql tuning
Asi bych zrušil index cas_2 a přehodil podmínky
... WHERE acc=4057 AND cas='031212';
Ovšem pokud má jen 300 záznamů, tak je přinejmenším podivné, že se to tak chová. Jako kdyby ta tabulka byla mezitím zamknuta.

Pro sloupec cas bych raději použil datový typ DATE. Bude se s ním lépe pracovat.
3.12.2012 21:46 nun
Rozbalit Rozbalit vše Re: mysql tuning
Je pravda, že vymazání jednoho indexu to na první pohled trochu zrychlilo, uvidíme, jestli se ten dotaz zase dostane do logů během zítřka.

Právě, že lock time byl prakticky nulovej :)

Ale je potěšující, že snad nedělám nějakou velkou botu :)

Dík§
Josef Kufner avatar 3.12.2012 21:57 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: mysql tuning
EXPLAIN!

A dej si tam jeden index nad dvěma sloupci 'cas' a 'acc'.
Hello world ! Segmentation fault (core dumped)
4.12.2012 19:04 nun
Rozbalit Rozbalit vše Re: mysql tuning
zkusil jsem ještě odmáznout ten jeden index a dát tam společný pro oba řádky:
id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra 
1	SIMPLE	adm_st	ref	cas	cas	24	const,const	1	Using where
Josef Kufner avatar 5.12.2012 00:07 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: mysql tuning
Wtf? Dej sem export té tabulky (jen strukturu bez dat).
Hello world ! Segmentation fault (core dumped)
3.12.2012 22:09 Kit
Rozbalit Rozbalit vše Re: mysql tuning
Pro 300 záznamů snad ani indexy nejsou potřebné. Spíš mi připadne, že je ta tabulka chybně normalizována. Neznám však problematiku aplikace, proto to nemohu jednoznačně tvrdit.
7.12.2012 15:11 j
Rozbalit Rozbalit vše Re: mysql tuning
"joiny vůbec nepoužívám"

Zasadni chyba - databaze tuhle praci vzdy odvede rychlejs a efektivnejs nez jakakoli nadstavba nad tim. Nevim sice jak je to postaveny, ale pokud budu mit rekneme clanek, kterej bude mit tabulku s hlavickou a tabulku s obsahem, je proste blbost selectovat 2x.

Jednoduse cim min selectu na zobrazeni stranky, tim lip (samo, v jistych mezich).

BTW: Vic indexu = pomalejsi update/insert => je treba to brat v potaz, a resit, zda se z DB spis cte nebo se do ni spis zapisuje.
7.12.2012 15:21 Kit
Rozbalit Rozbalit vše Re: mysql tuning
S JOINem se musí opatrně, protože výsledek není indexován. Někdy je lepší nejprve provést selekci a teprve výsledek joinovat.
okbob avatar 7.12.2012 18:41 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
Rozbalit Rozbalit vše Re: mysql tuning
Většina databází - včetně nejnovější MySQL podporují hashjoin - tudíž fakt, že tam není index nemusí být problém. Naopak provedení selekce a její uložení (např. do dočasné tabulky, aby bylo co joinovat) může znamenat množství IO nebo vynucení používání triků (jako jsou memory tables, kde jste ale limitovaní velikostí RAM a vyhrazené paměti), se kterými je spojeno dost práce a které většinou jsou nějakým způsobem limitované.

V drtivé většině situací, a pokud máte alespoň trochu rozumně navrženou databázi, je JOIN ta nejlepší varianta. Opravdu nemá cenu používat SQL způsobem, který vyhovoval MySQL 4.1. Za chvilku budeme mít rok 2013 - a i MySQL už bude mít většinu funkcionality, která je běžná - hashjoiny, statistiky, ...
7.12.2012 18:52 Kit
Rozbalit Rozbalit vše Re: mysql tuning
Ukládání výsledků selekce do dočasné tabulky jsem opravdu neměl na mysli. Obvykle stačí je uzavřít do závorek a pracovat s nimi jako s další tabulkou.
okbob avatar 7.12.2012 22:18 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
Rozbalit Rozbalit vše Re: mysql tuning
to je tzv. derivovaná tabulka - ale ta žádné indexy nemá - a obyčejně vlastně ani neexistuje - starší verze MySQL ji tuším materializovaly - v jiných databázích se provádí tzv. flattening - kdy se derivovaná tabulka rozpouští v dotazu.
11.12.2012 17:13 j
Rozbalit Rozbalit vše Re: mysql tuning
K tomu asi toliko, ze (samo v zavislosti na databazi) syntax dotazu je naprosto nepodstana. Databaze si kazdej prevadi do nejaky "optimalni" podoby, takze format by spis mel byt predevsim prehledny. Vynutit nejake chovani ke query nemusi byt vubec jednoduche, a navic to casto vede jen k tomu, ze sice nekde ziskam milisekundu, ale jinde ztratim sekundu.

A trebas prave vkladani dotazu do sebe je (IMO) peknej bordel - specilene kdyz to pak clovek po nekom zkouma, z zjistuje, co to vlastne dela.

BTW: Povedlo se mi nejmenovany "ERP" nejmenovane firmy zrychlit(v nekterych oblastech) o 4 rady ... tomu nerikam optimalizece, tomu rikam, ze by navrhar DB a vyvojari meli viset za koule v pruvanu.
Josef Kufner avatar 3.12.2012 12:48 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: mysql tuning
Odpovědět | | Sbalit | Link | Blokovat | Admin
V první řadě loguj SQL dotazy a doby jejich trvání. Na to si doplň podporu přímo do aplikace, aby jsi tam viděl i odkud dotazy pochází. Pak uvidíš, co má smysl optimalizovat.

Druhá velmi užitečná věc je Xdebug + KCachegrind. Tedy normální profiler. Tam uvidíš, v čem ztrácíš výkon a co z kódu vykopat ven. Doporučuju to instalovat na lokální vývojový server, zapnout si volbu xdebug.profiler_enable_trigger a nainstalovat do prohlížeče doplňek na ovládání (např. Xdebug helper pro Chrome).

Já obvykle přidávám do svých aplikací jednoduchý profiler, který sbírá základní statistiky i na produkčním serveru. Takže pak vidím, kde to drhne na reálném provozu, ale ztráty na výkonu jsou minimální (pár vhodně umístěných microtime a update jednoho souboru s agregovanými daty). K tomu se ale Xdebug moc nehodí, neboť na jeden request je schopný zalogovat i několik desítek MB dat.
Hello world ! Segmentation fault (core dumped)
3.1.2013 10:34 PetrHL | skóre: 17 | blog: petr_h | Neratovice
Rozbalit Rozbalit vše Re: mysql tuning
Odpovědět | | Sbalit | Link | Blokovat | Admin
A za sebe bych doporučoval přechod na InnoDB. Výkonnost je někde jinde, pokud DB nemáte jen readonly, určitě se to vyplatí. Pokud hodně zapisujete, chtělo by to další optimalizace. Sám mám VPS u WEDOS (3GB RAM), DB má asi 4GB (několik M záznamů), dost se do ní zapisuje a bez optimalizací bych tu VPS udusil kvůli čekání na I/O. Návštěv mám kolem 28k za měsíc, page views něco přes 240k.
"Do, or do not. There is no 'try.'" -- Jedi Master Yoda | CQRLOG | CQRPROP | HamQTH | Domů

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.