sql >> Databáze >  >> RDS >> MariaDB

Zpracování velkých objemů dat pomocí MySQL a MariaDB

Většina databází se postupem času zvětšuje. Růst není vždy dostatečně rychlý, aby ovlivnil výkon databáze, ale určitě existují případy, kdy k tomu dojde. Když se tak stane, často přemýšlíme, co by se dalo udělat pro snížení tohoto dopadu a jak můžeme zajistit hladký provoz databáze při práci s daty ve velkém měřítku.

Nejprve se pokusíme definovat, co znamená „velký objem dat“? Pro MySQL nebo MariaDB je to nekomprimovaný InnoDB. InnoDB funguje tak, že silně těží z dostupné paměti – hlavně z fondu vyrovnávací paměti InnoDB. Dokud se tam data vejdou, je přístup k disku minimalizován na zpracování pouze zápisů – čtení se obsluhuje mimo paměť. Co se stane, když data přerostou paměť? Stále více dat se musí číst z disku, když je potřeba přistupovat k řádkům, které aktuálně nejsou v mezipaměti. Když se objem dat zvýší, pracovní zátěž se přepne z vazby na CPU směrem k I/O. To znamená, že úzkým hrdlem již není CPU (což byl případ, kdy se data vešla do paměti – přístup k datům v paměti je rychlý, transformace dat a agregace pomalejší), ale spíše je to I/O subsystém (CPU operace s daty jsou rychlejší než přístup k datům z disku.) Se zvýšeným přijetím flash není pracovní zátěž vázaná na I/O tak hrozná, jako bývala v dobách rotujících disků (náhodný přístup je mnohem rychlejší s SSD), ale výkonový hit stále existuje .

Další věc, kterou musíme mít na paměti, že se obvykle staráme pouze o aktivní datovou sadu. Jistě, můžete mít ve svém schématu terabajty dat, ale pokud máte přístup pouze k posledním 5 GB, je to vlastně docela dobrá situace. Jistě, stále to představuje provozní problémy, ale z hlediska výkonu by to mělo být stále v pořádku.

Předpokládejme pro účely tohoto blogu, a to není vědecká definice, že velkým objemem dat máme na mysli případ, kdy velikost aktivních dat výrazně převyšuje velikost paměti. Může to být 100 GB, když máte 2 GB paměti, může to být 20 TB, když máte 200 GB paměti. Bodem zlomu je, že vaše pracovní zátěž je přísně vázána na I/O. Buďte s námi, zatímco budeme diskutovat o některých možnostech, které jsou k dispozici pro MySQL a MariaDB.

Rozdělení

Historickým (ale dokonale platným) přístupem ke zpracování velkých objemů dat je implementace dělení. Myšlenka za tím je rozdělit tabulku na oddíly, jakési podtabulky. Rozdělení probíhá podle pravidel definovaných uživatelem. Podívejme se na některé příklady (příklady SQL jsou převzaty z dokumentace MySQL 8.0)

MySQL 8.0 přichází s následujícími typy dělení:

  • ROZSAH
  • SEZNAM
  • SLOUPCE
  • HASH
  • KLÍČ

Může také vytvářet pododdíly. Nechystáme se zde přepisovat dokumentaci, ale přesto bychom vám rádi poskytli určitý přehled o tom, jak oddíly fungují. Chcete-li vytvořit oddíly, musíte definovat rozdělovací klíč. Může to být sloupec nebo v případě RANGE nebo LIST více sloupců, které budou použity k definování toho, jak mají být data rozdělena do oddílů.

Rozdělení HASH vyžaduje, aby uživatel definoval sloupec, který bude hašován. Poté budou data rozdělena do uživatelem definovaného počtu oddílů na základě této hodnoty hash:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;

V tomto případě bude hash vytvořen na základě výsledku generovaného funkcí YEAR() ve sloupci ‚najato‘.

Rozdělení KEY je podobné s tou výjimkou, že uživatel definuje, který sloupec má být hašován, a zbytek je na MySQL, jak se s ním vypořádá.

Zatímco oddíly HASH a KEY náhodně distribuovaly data napříč počtem oddílů, RANGE a LIST umožňují uživateli rozhodnout, co dělat. RANGE se běžně používá s časem nebo datem:

CREATE TABLE quarterly_report_status (
    report_id INT NOT NULL,
    report_status VARCHAR(20) NOT NULL,
    report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
    PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
    PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
    PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
    PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
    PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
    PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
    PARTITION p9 VALUES LESS THAN (MAXVALUE)
);

Lze jej také použít s jinými typy sloupců:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT NOT NULL,
    store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
    PARTITION p0 VALUES LESS THAN (6),
    PARTITION p1 VALUES LESS THAN (11),
    PARTITION p2 VALUES LESS THAN (16),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

Oddíly LIST fungují na základě seznamu hodnot, který třídí řádky mezi více oddíly:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY LIST(store_id) (
    PARTITION pNorth VALUES IN (3,5,6,9,17),
    PARTITION pEast VALUES IN (1,2,10,11,19,20),
    PARTITION pWest VALUES IN (4,12,13,14,18),
    PARTITION pCentral VALUES IN (7,8,15,16)
);

Možná se ptáte, jaký má smysl používat oddíly? Hlavním bodem je, že vyhledávání jsou výrazně rychlejší než u tabulky bez oddílů. Řekněme, že chcete vyhledat řádky, které byly vytvořeny v daném měsíci. Pokud máte v tabulce uložena data za několik let, bude to problém – bude nutné použít index a jak víme, indexy pomáhají najít řádky, ale přístup k těmto řádkům povede k hromadě náhodných čtení z celý stůl. Pokud máte oddíly vytvořené na roční bázi, MySQL může pouze číst všechny řádky z tohoto konkrétního oddílu – není třeba přistupovat k indexu, není třeba provádět náhodná čtení:stačí přečíst všechna data z oddílu postupně a jsme vše nastaveno.

Oddíly jsou také velmi užitečné při řešení rotace dat. Pokud MySQL dokáže snadno identifikovat řádky k odstranění a namapovat je na jeden oddíl, místo spuštění tabulky DELETE FROM WHERE …, která použije index k vyhledání řádků, můžete oddíl zkrátit. To je extrémně užitečné při dělení na RANGE - pokud se budeme držet výše uvedeného příkladu, pokud chceme uchovávat data pouze 2 roky, můžeme snadno vytvořit úlohu cron, která odstraní starý oddíl a vytvoří nový, prázdný na příští měsíc.

Komprese InnoDB

Pokud máme velký objem dat (nemusíme nutně myslet na databáze), první co nás napadne je zkomprimovat je. Existuje mnoho nástrojů, které poskytují možnost komprimovat vaše soubory a výrazně zmenšit jejich velikost. InnoDB má také možnost - jak MySQL, tak MariaDB podporují kompresi InnoDB. Hlavní výhodou použití komprese je snížení I/O aktivity. Data, když jsou komprimována, jsou menší, takže je rychlejší číst a zapisovat. Typická stránka InnoDB má velikost 16 KB, pro SSD to jsou 4 I/O operace pro čtení nebo zápis (SSD obvykle používá 4KB stránky). Pokud se nám podaří zkomprimovat 16KB na 4KB, snížíme pouze I/O operace o čtyři. Ve skutečnosti to moc nepomáhá, pokud jde o poměr datové sady k paměti. Vlastně to může ještě zhoršit – MySQL, aby s daty fungovalo, musí stránku dekomprimovat. Přesto čte komprimovanou stránku z disku. Výsledkem je, že fond vyrovnávací paměti InnoDB uchovává 4 kB komprimovaných dat a 16 kB nekomprimovaných dat. Samozřejmě existují algoritmy pro odstranění nepotřebných dat (nekomprimovaná stránka bude odstraněna, pokud to bude možné, v paměti zůstane pouze komprimovaná), ale v této oblasti nelze očekávat příliš velké zlepšení.

Je také důležité mít na paměti, jak funguje komprese ohledně úložiště. Jednotky SSD jsou v dnešní době normou pro databázové servery a mají několik specifických vlastností. Jsou rychlé, je jim jedno, zda je provoz sekvenční nebo náhodný (i když stále preferují sekvenční přístup před náhodným). Jsou drahé pro velké objemy. Trpí „opotřebováním“, protože zvládnou omezený počet cyklů zápisu. Zde výrazně pomáhá komprese - zmenšením velikosti dat na disku snížíme náklady na úložnou vrstvu pro databázi. Zmenšením velikosti dat, která zapisujeme na disk, prodloužíme životnost SSD.

Bohužel, i když komprese pomáhá, pro větší objemy dat stále nemusí stačit. Dalším krokem by bylo hledat něco jiného než InnoDB.

MyRocks

MyRocks je úložný engine dostupný pro MySQL a MariaDB, který je založen na jiném konceptu než InnoDB. Můj kolega Sebastian Insausti má pěkný blog o používání MyRocks s MariaDB. Podstatou je, že díky svému designu (používá Log Structured Merge, LSM) je MyRocks z hlediska komprese výrazně lepší než InnoDB (který je založen na struktuře B+Tree). MyRocks je navržen pro zpracování velkého množství dat a pro snížení počtu zápisů. Vznikl z Facebooku, kde jsou objemy dat velké a požadavky na přístup k datům vysoké. Tedy úložiště SSD – přesto je v tak velkém měřítku každý zisk v kompresi obrovský. MyRocks mohou poskytnout dokonce až 2x lepší kompresi než InnoDB (což znamená, že snížíte počet serverů o dva). Je také navržen tak, aby snížil zesílení zápisu (počet zápisů potřebných ke zpracování změny obsahu řádku) – vyžaduje 10x méně zápisů než InnoDB. To samozřejmě snižuje zátěž I/O, ale co je ještě důležitější, prodlouží životnost SSD desetkrát ve srovnání se stejnou zátěží pomocí InnoDB). Z hlediska výkonu platí, že čím menší objem dat, tím rychlejší je přístup, takže úložné stroje mohou také pomoci rychleji dostat data z databáze (i když to při navrhování MyRocks nebylo nejvyšší prioritou).

Sloupcová datová úložiště

Související zdroje ClusterControl Performance Management Porozumění účinkům vysoké latence v řešení MySQL a MariaDB s vysokou dostupností Cheat Sheet pro výkon MySQL

V určitém okamžiku můžeme pouze připustit, že takový objem dat pomocí MySQL nezvládneme. Jistě, můžete to rozbít, můžete dělat různé věci, ale nakonec to prostě nedává smysl. Je čas hledat další řešení. Jedním z nich by bylo použití sloupcových datových úložišť – databází, které jsou navrženy s ohledem na analýzu velkých dat. Jistě, nepomohou s provozem typu OLTP, ale analytika je v dnešní době do značné míry standardní, protože společnosti se snaží být řízeny daty a rozhodovat se na základě přesných čísel, nikoli náhodných dat. Existuje mnoho sloupcových datových úložišť, ale rádi bychom zde zmínili dvě z nich. MariaDB AX a ClickHouse. Máme několik blogů, které vysvětlují, co je MariaDB AX a jak lze MariaDB AX používat. Co je důležité, MariaDB AX lze škálovat ve formě clusteru, což zlepšuje výkon. ClickHouse je další možností pro spouštění analýzy – ClickHouse lze snadno nakonfigurovat tak, aby replikoval data z MySQL, jak jsme diskutovali v jednom z našich blogových příspěvků. Je rychlý, je zdarma a lze jej také použít k vytvoření clusteru a ke sdílení dat pro ještě lepší výkon.

Závěr

Doufáme, že vám tento příspěvek na blogu poskytl informace o tom, jak velké objemy dat lze zpracovávat v MySQL nebo MariaDB. Naštěstí máme k dispozici několik možností a nakonec, pokud to opravdu nefunguje, existují dobré alternativy.


  1. Převést „datetimeoffset“ na „datetime2“ v SQL Server (příklady T-SQL)

  2. Deset nejlepších nástrojů GUI MySQL

  3. Jak přežít audit Oracle

  4. Jak automaticky znovu zadat dotaz pomocí LoaderManager