Zatížení databáze MySQL je určeno počtem dotazů, které zpracovává. Existuje několik situací, ve kterých může vzniknout pomalost MySQL. První možností je, pokud existují nějaké dotazy, které nepoužívají správné indexování. Když dotaz nemůže využít index, server MySQL musí ke zpracování tohoto dotazu použít více zdrojů a času. Sledováním dotazů máte možnost přesně určit kód SQL, který je hlavní příčinou zpomalení, a opravit jej dříve, než dojde ke snížení celkového výkonu.
V tomto příspěvku na blogu se chystáme zdůraznit funkci Query Outlier dostupnou v ClusterControl a uvidíme, jak nám může pomoci zlepšit výkon databáze. Obecně ClusterControl provádí vzorkování dotazů MySQL dvěma způsoby:
- Načtěte dotazy ze schématu výkonu (doporučeno ).
- Analyzujte obsah MySQL Slow Query.
Pokud je schéma výkonu zakázáno, ClusterControl pak jako výchozí použije protokol Slow Query. Chcete-li se dozvědět více o tom, jak to ClusterControl provádí, podívejte se na tento blogový příspěvek Jak používat ClusterControl Query Monitor pro MySQL, MariaDB a Percona Server.
Co jsou odlehlé hodnoty dotazu?
Odlehlá hodnota je dotaz, který trvá déle než normální doba dotazu tohoto typu. Neberte to doslova jako „špatně napsané“ dotazy. Mělo by se s tím zacházet jako s potenciálními neoptimálními společnými dotazy, které by bylo možné zlepšit. Po několika vzorcích a když má ClusterControl dostatek statistik, může určit, zda je latence vyšší než normální (2 sigmas + average_query_time), pak jde o odlehlou hodnotu a bude přidána do odlehlé hodnoty dotazu.
Tato funkce je závislá na funkci Nejčastější dotazy. Pokud je povoleno sledování dotazů a jsou zachyceny a naplněny hlavní dotazy, odlehlé hodnoty dotazů je shrnují a poskytnou filtr založený na časovém razítku. Chcete-li zobrazit seznam dotazů, které vyžadují pozornost, přejděte do ClusterControl -> Query Monitor -> Query Outliers a měli byste vidět některé uvedené dotazy (pokud existují):
Jak můžete vidět na snímku obrazovky výše, odlehlé hodnoty jsou v podstatě dotazy, které trvalo alespoň 2krát déle, než je průměrná doba dotazu. Nejprve první záznam, průměrný čas je 34,41 ms, zatímco čas dotazu odlehlé hodnoty je 140 ms (více než 2krát více než průměrný čas). Podobně u dalších položek jsou sloupce Doba dotazu a Prům. doba dotazu dvě důležité věci, které odůvodňují nevyřízené položky konkrétního odlehlého dotazu.
Je relativně snadné najít vzorec konkrétní odlehlé hodnoty dotazu, když se podíváte na větší časové období, například před týdnem, jak je zvýrazněno na následujícím snímku obrazovky:
Kliknutím na každý řádek zobrazíte celý dotaz, který je skutečně užitečné pro určení a pochopení problému, jak je ukázáno v další části.
Oprava odlehlých hodnot dotazu
Abychom napravili odlehlé hodnoty, musíme porozumět povaze dotazu, úložišti tabulek, verzi databáze, typu shlukování a dopadu dotazu. V některých případech odlehlý dotaz skutečně nesnižuje celkový výkon databáze. Stejně jako v tomto příkladu jsme viděli, že dotaz vyčníval celý týden a byl to jediný typ dotazu, který byl zachycen, takže je pravděpodobně dobrý nápad tento dotaz opravit nebo vylepšit, pokud je to možné.
Stejně jako v našem případě je odlehlý dotaz:
SELECT i2l.country_code AS country_code, i2l.country_name AS country_name
FROM ip2location i2l
WHERE (i2l.ip_to >= INET_ATON('104.144.171.139')
AND i2l.ip_from <= INET_ATON('104.144.171.139'))
LIMIT 1
OFFSET 0;
A výsledek dotazu je:
+--------------+---------------+
| country_code | country_name |
+--------------+---------------+
| US | United States |
+--------------+---------------+
Pomocí EXPLAIN
Dotaz je pouze pro čtení dotazem pro výběr rozsahu k určení informací o zeměpisné poloze uživatele (kód země a název země) pro IP adresu v tabulce ip2location. Použití příkazu EXPLAIN nám může pomoci pochopit plán provádění dotazu:
mysql> EXPLAIN SELECT i2l.country_code AS country_code, i2l.country_name AS country_name
FROM ip2location i2l
WHERE (i2l.ip_to>=INET_ATON('104.144.171.139')
AND i2l.ip_from<=INET_ATON('104.144.171.139'))
LIMIT 1 OFFSET 0;
+----+-------------+-------+------------+-------+--------------------------------------+-------------+---------+------+-------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+--------------------------------------+-------------+---------+------+-------+----------+------------------------------------+
| 1 | SIMPLE | i2l | NULL | range | idx_ip_from,idx_ip_to,idx_ip_from_to | idx_ip_from | 5 | NULL | 66043 | 50.00 | Using index condition; Using where |
+----+-------------+-------+------------+-------+--------------------------------------+-------------+---------+------+-------+----------+------------------------------------+
Dotaz se provede se skenováním rozsahu v tabulce pomocí indexu idx_ip_from s 50 % potenciálních řádků (filtrováno).
Správný modul úložiště
Při pohledu na strukturu tabulky ip2location:
mysql> SHOW CREATE TABLE ip2location\G
*************************** 1. row ***************************
Table: ip2location
Create Table: CREATE TABLE `ip2location` (
`ip_from` int(10) unsigned DEFAULT NULL,
`ip_to` int(10) unsigned DEFAULT NULL,
`country_code` char(2) COLLATE utf8_bin DEFAULT NULL,
`country_name` varchar(64) COLLATE utf8_bin DEFAULT NULL,
KEY `idx_ip_from` (`ip_from`),
KEY `idx_ip_to` (`ip_to`),
KEY `idx_ip_from_to` (`ip_from`,`ip_to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
Tato tabulka je založena na databázi umístění IP2 a je zřídkakdy aktualizována/zapsána, obvykle pouze první den kalendářního měsíce (doporučeno dodavatelem). Jednou z možností je tedy převést tabulku na úložiště MyISAM (MySQL) nebo Aria (MariaDB) s pevným formátem řádků, abyste získali lepší výkon pouze pro čtení. Všimněte si, že to platí pouze v případě, že používáte MySQL nebo MariaDB samostatně nebo replikaci. Na Galera Cluster a Group Replication se prosím držte úložiště InnoDB (pokud nevíte, co děláte).
Pro převod tabulky z InnoDB na MyISAM s pevným formátem řádků jednoduše spusťte následující příkaz:
ALTER TABLE ip2location ENGINE=MyISAM ROW_FORMAT=FIXED;
Při našem měření s 1 000 náhodnými testy vyhledávání IP adres se výkon dotazu zlepšil přibližně o 20 % díky MyISAM a pevnému formátu řádků:
- Průměrná doba (InnoDB):21,467823 ms
- Průměrná doba (MyISAM Fixed):17,175942 ms
- Zlepšení:19,992157565301 %
Můžete očekávat, že tento výsledek bude okamžitě po změně tabulky. Není nutná žádná úprava na vyšší úrovni (aplikace/nástroj pro vyrovnávání zatížení).
Ladění dotazu
Dalším způsobem je zkontrolovat plán dotazů a použít efektivnější přístup pro lepší plán provádění dotazů. Stejný dotaz lze také napsat pomocí poddotazu, jak je uvedeno níže:
SELECT `country_code`, `country_name` FROM
(SELECT `country_code`, `country_name`, `ip_from`
FROM `ip2location`
WHERE ip_to >= INET_ATON('104.144.171.139')
LIMIT 1)
AS temptable
WHERE ip_from <= INET_ATON('104.144.171.139');
Vyladěný dotaz má následující plán provádění dotazu:
mysql> EXPLAIN SELECT `country_code`,`country_name` FROM
(SELECT `country_code`, `country_name`, `ip_from`
FROM `ip2location`
WHERE ip_to >= INET_ATON('104.144.171.139')
LIMIT 1)
AS temptable
WHERE ip_from <= INET_ATON('104.144.171.139');
+----+-------------+--------------+------------+--------+---------------+-----------+---------+------+-------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+------------+--------+---------------+-----------+---------+------+-------+----------+-----------------------+
| 1 | PRIMARY | <derived2> | NULL | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | ip2location | NULL | range | idx_ip_to | idx_ip_to | 5 | NULL | 66380 | 100.00 | Using index condition |
+----+-------------+--------------+------------+--------+---------------+-----------+---------+------+-------+----------+-----------------------+
Pomocí poddotazu můžeme optimalizovat dotaz pomocí odvozené tabulky, která se zaměřuje na jeden index. Dotaz by měl vrátit pouze 1 záznam, kde hodnota ip_to je větší nebo rovna hodnotě adresy IP. To umožňuje potenciálním řádkům (filtrovaným) dosáhnout 100 %, což je nejúčinnější. Poté zkontrolujte, zda je ip_from menší nebo roven hodnotě IP adresy. Pokud ano, měli bychom najít záznam. Jinak IP adresa v tabulce ip2location neexistuje.
V našem měření se výkon dotazu zlepšil přibližně o 99 % pomocí dílčího dotazu:
- Průměrná doba (InnoDB + skenování rozsahu):22,87112 ms
- Průměrná doba (InnoDB + dílčí dotaz):0,14744 ms
- Zlepšení:99,355344207017 %
S výše uvedenou optimalizací vidíme u tohoto typu dotazu dobu provádění dotazu pod milisekundy, což je obrovské zlepšení vzhledem k předchozí průměrné době 22 ms. Abychom mohli těžit z tohoto vyladěného dotazu, musíme provést určité úpravy na vyšší úrovni (aplikace/nástroj pro vyrovnávání zatížení).
Oprava nebo přepisování dotazu
Opravte své aplikace tak, aby používaly vyladěný dotaz, nebo přepište odlehlý dotaz, než se dostane na databázový server. Můžeme toho dosáhnout pomocí nástroje pro vyrovnávání zatížení MySQL, jako je ProxySQL (pravidla dotazů) nebo MariaDB MaxScale (filtr přepisování příkazů), nebo pomocí pluginu MySQL Query Rewriter. V následujícím příkladu používáme ProxySQL před naším databázovým clusterem a můžeme jednoduše vytvořit pravidlo pro přepsání pomalejšího dotazu na rychlejší, například:
Uložte pravidlo dotazu a sledujte stránku Odlehlé hodnoty dotazu v ClusterControl. Tato oprava zjevně odstraní odlehlé dotazy ze seznamu po aktivaci pravidla dotazu.
Závěr
Odlehlé hodnoty dotazů jsou proaktivní nástroj pro sledování dotazů, který nám může pomoci pochopit a vyřešit problém s výkonem dříve, než se vymkne kontrole. Jak vaše aplikace roste a stává se náročnější, může vám tento nástroj pomoci udržet slušný výkon databáze.