it-swarm-eu.dev

MySQL LOAD DATA INFILE se po několika vstupech s InnoDB zpomalí o 80%

Načítám 100 GB soubor pomocí LOAD DATA INFILE. S MyISAMem jsem měl dobrý úspěch, pár hodin a hotovo.

Zkouším to teď pomocí InnoDB. Zatížení začíná rychle rychlostí vyšší než 10 MB/s (při sledování růstu souborů tabulky, file_per_table je zapnuto).

Ale po asi 5 GB dat se zpomalí na rozsah 2-4MB/s, protože když dostanu více než 20 GB, bylo to kolem 2 MB/s.

Velikost fondů vyrovnávacích pamětí InnoDB je 8G. A před spuštěním příkazu LOAD DATA INFILE jsem provedl následující:

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

Nevidím důvod, proč to začíná dobře a časem zpomaluje.

Stejným nastavením jsem také spustil stejný příkaz LOAD DATA INFILE s tabulkou pomocí InnoDB a MyISAM a testovacího datového souboru 5 GB, MyISAM byl 20x rychlejší:

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

Ještě něco, co bych měl zvážit vyzkoušet? Motor MyISAM je schopen udržovat rychlost zátěže mnohem lépe.


Další podrobnosti:

  • Pokusil jsem se nahrát soubory jednotlivě, žádný rozdíl.

  • Mimochodem, mám 150 souborů po 500 MB, v každém souboru jsou klíče seřazeny.

  • Po získání 40 GB za noc, o 12 hodin později, byla rychlost zátěže snížena na 0,5 MB/s, což znamená, že operace je prakticky nemožná.

  • Na jiných fórech jsem nenašel žádné další odpovědi na podobné otázky, zdá se mi, že InnoDB nepodporuje načítání velkého množství dat do tabulek o velikosti několika GB.

14
David Parks

POZOROVÁNÍ # 1

Všiml jsem si, že jsi vypnul autocommit. To nashromadí tolik dat v ibdata1. Proč?

V ibdata1 je uloženo sedm (7) tříd informací:

  • Datové stránky pro tabulky InnoDB
  • Indexové stránky pro tabulky InnoDB
  • Datový slovník
  • Vyrovnávací paměť s dvojitým zápisem
    • Bezpečnostní síť pro zabránění poškození dat
    • Pomáhá obejít OS pro ukládání do mezipaměti
  • Vložit vyrovnávací paměť (Usnadňuje změny sekundárních indexů)
  • Vrácení segmentů
  • Zrušit protokoly
  • Klepnutím sem zobrazíte obrázkovou reprezentaci ibdata1

Některé z těchto informací jsou viditelné pro určité transakce v závislosti na úrovni izolace. Takové akce by mohly způsobit nezamýšlené zámky primárních klíčů a mnoho fantomových dat . Když se tyto dvě věci zvýší, měli byste očekávat, že se zpomalí.

Doporučení: Nechte autocommit na

POZOROVÁNÍ # 2

Vidím, že to máte:

alter table item_load disable keys;

DISABLE KEYS nepracuje s InnoDB . Zde je proč:

  • MyISAM: DISABLE KEYS jednoduše vypne aktualizaci sekundárního indexu pro tabulku MyISAM. Když hromadíte INSERT do tabulky MyISAM s deaktivovanými klíči, dojde k rychlému načtení tabulky spolu s budováním PRIMARY KEY a všech jedinečných indexů. Když spustíte ENABLE KEYS, všechny sekundární indexy jsou postaveny lineárně na stole a připojeny k .MYD.
  • InnoDB: Jak je vidět na interním obrázku InnoDB, systém tablespave ibdata1 má strukturu vyhrazenou pro vložení sekundárních indexů. V současné době neexistuje ustanovení pro zpracování indexů stejně jako u MyISAM.

Pro ilustraci si všimněte mého pokusu o spuštění DISABLE KEYS v tabulce InnoDB v MySQL

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

POZOROVÁNÍ # 3

Všimli jste si, že MyISAM se načítá 20x rychleji než InnoDB. Chtěli byste, aby to bylo 24-25krát rychlejší? Potom spusťte následující:

ALTER TABLE item_load ROW_FORMAT=Fixed;

Tím se zrychlí INSERT krát 20-25% bez jakýchkoli dalších změn DDL . Vedlejší účinek: Tabulka MyISAM může růst o 80% až 100%, případně větší.

Dalo by se to spustit také v tabulce InnoDB, ale chování ACID a [~ # ~] mvcc [~ # ~] z InnoDB by stále bylo překážkou jeho výkonu, zvláště pokud by se pole VARCHAR výrazně zvýšila, bude zapsána do ibdata1.

7
RolandoMySQLDBA

Konečnou odpovědí na tuto otázku bylo nepoužít InnoDB pro rozsáhlou referenční tabulku. MyISAM křičí rychle, téměř na plný výkon rychlosti disku pro celé zatížení, InnoDB se srazí dolů. MyISAM je jednoduchý, ale v tomto případě jsou to i požadavky této tabulky. Pro jednoduchou referenční tabulku s hromadným zatížením přes LOAD DATA INFILE je MyISAM cestou, která je zatím dobrá.

Ale všimněte si, že pokud spustíte tabulky MyISAM a InnoDB, budete muset zvážit přidělení paměti pro 2 mechanismy ukládání do mezipaměti, každý motor má svůj vlastní jedinečný ukládání do mezipaměti, které vyžaduje samostatné přidělení paměti.

6
David Parks

Můžete zkusit rozdělit vstupní soubory na menší kousky.

Osobně k tomu používám http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html .

Co se stane, když během importu obdržíte stolní zámek pro tabulku? Možná blokování úrovně InnoDB to zpomalí (MyISAM používá zámek tabulky).

Můžete si také přečíst další nápady: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql

5
bnadland

Pokud váš PK není AUTO_INCREMENT nebo data v souboru csv nejsou na PK tříděna, mohlo by to ovlivnit výkon načtení dat. Protože tabulka v MySQL je index, takže všechna data jsou uložena v seřazeném pořadí, pokud hodnota PK není na AUTO_INCREMENT, než MySQL musí udělat mnoho datových posunů, aby byla data uložena v seřazeném pořadí. To je důvod pro pomalejší načítání dat, když začíná velikost tabulky.

Načítám soubor CSV s kapacitou 91 GB pomocí PK na AUTO_INCREMENT pomocí LOAD DATA INFILE a nevidím žádný pokles v mé propustnosti. Dostávám 140K až 145K inzerátů za sekundu. Používání Percona MySQL 5.6.38

2
KKYadav