2015-05-27 4 views
1

Я пытаюсь оптимизировать большую (68K строку) вставку в промежуточную таблицу. Я создал таблицу как таблицу движка MEMORY, и никаких индексов или внешних ключей вообще нет. Когда мой процесс ETL начинает вставлять, вставки выполняются, но очень медленно; полная загрузка занимает более часа.MySQL вставляет очень медленно в таблицу MEMORY

Вот определение таблицы из шоу таблицы создания:

CREATE TABLE `pub_tair_germplasm` (
    `germplasm_id` int(12) DEFAULT NULL, 
    `name` varchar(100) DEFAULT NULL, 
    `original_name` varchar(100) DEFAULT NULL, 
    `sp_growth_conditions` varchar(2048) DEFAULT NULL, 
    `description` varchar(2048) DEFAULT NULL, 
    `description_uc` varchar(2048) DEFAULT NULL, 
    `is_mutant` varchar(1) DEFAULT NULL, 
    `is_aneuploid` varchar(1) DEFAULT NULL, 
    `ploidy` varchar(4) DEFAULT NULL, 
    `species_variant_id` int(12) DEFAULT NULL, 
    `taxon_id` int(12) DEFAULT NULL, 
    `aneuploid_chromosome` int(10) DEFAULT NULL, 
    `date_entered` date DEFAULT NULL, 
    `date_last_modified` date DEFAULT NULL, 
    `tair_object_id` bigint(19) DEFAULT NULL, 
    `is_obsolete` varchar(1) DEFAULT NULL, 
    `tair_object_type_id` int(12) DEFAULT NULL, 
    `germplasm_type` varchar(20) DEFAULT NULL 
) ENGINE=MEMORY DEFAULT CHARSET=latin1 

Вот вставка:

INSERT INTO pub_tair_germplasm(
    germplasm_id, 
    name, 
    original_name, 
    sp_growth_conditions, 
    description, 
    description_uc, 
    is_mutant, 
    is_aneuploid, 
    ploidy, 
    species_variant_id, 
    taxon_id, 
    aneuploid_chromosome, 
    date_entered, 
    date_last_modified, 
    tair_object_id, 
    is_obsolete, 
    tair_object_type_id, 
    germplasm_type) 
VALUES (
    $germplasm_id, 
    $name, 
    $original_name, 
    $sp_growth_conditions, 
    $description, 
    $description_uc, 
    CASE $is_mutant WHEN 'F' THEN 'n' WHEN 'T' THEN 'y' ELSE 'y' END, 
    CASE $is_aneuploid WHEN 'F' THEN 'n' WHEN 'T' THEN 'y' ELSE 'y' END, 
    $ploidy, 
    $species_variant_id, 
    $taxon_id, 
    $aneuploid_chromosome, 
    $date_entered, 
    $date_last_modified, 
    $tair_object_id, 
    $is_obsolete, 
    $tair_object_type_id, 
    $type) 

Это делается через Clover/ETL, который обычно вставляет очень быстро, используя JDBC пакетирование с размер партии 5000. Переменные значений - это ссылки на CloverETL. Подобные вставки на Oracle занимают секунды в обычной таблице. Все это делается в одной транзакции, не фиксируется до тех пор, пока не будут вставлены все строки (требование приложения).

Пока вставляются вставки, верхний показывает, что оба процессора используются на 0,3%.

правок:

Для следующего теста, я увеличил максимальный размер кучи таблицы до 1 ГБ, достаточно легко провести всю таблицу:

mysql> select @@max_heap_table_size; 
+-----------------------+ 
| @@max_heap_table_size | 
+-----------------------+ 
|    999999488 | 
+-----------------------+ 

Список процессов при запуске:

mysql> SHOW FULL PROCESSLIST; 
+----+------+-----------+-------+---------+------+-------+-----------------------+ 
| Id | User | Host  | db | Command | Time | State | Info     | 
+----+------+-----------+-------+---------+------+-------+-----------------------+ 
| 3 | root | localhost | mysql | Query | 0 | NULL | SHOW FULL PROCESSLIST | 
+----+------+-----------+-------+---------+------+-------+-----------------------+ 
1 row in set (0.00 sec) 

список процессов во время работы:

mysql> SHOW FULL PROCESSLIST; 
+----+---------+--------------------------------------------+-------+---------+------+-------+-----------------------+ 
| Id | User | Host          | db | Command | Time | State | Info     | 
+----+---------+--------------------------------------------+-------+---------+------+-------+-----------------------+ 
| 4 | pubuser | c-67-188-135-136.hsd1.ca.comcast.net:55928 | pub | Sleep | 0 |  | NULL     | 
| 5 | root | localhost         | mysql | Query | 0 | NULL | SHOW FULL PROCESSLIST | 
+----+---------+--------------------------------------------+-------+---------+------+-------+-----------------------+ 
2 rows in set (0.00 sec) 

Я включил общий файл журнала; он показывает команду CloverETL настройки среды, выпущенную, затем переходит в ряд вставок:

150528 20:22:54  4 Connect [email protected] on pub 
        4 Query  /* mysql-connector-java-5.1.20 (Revision: [email protected]) */SHOW VARIABLES WHERE Variable_name ='langua 
ge' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name 
= 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isola 
tion' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_cas 
e_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_nam 
e = 'query_cache_size' OR Variable_name = 'init_connect' 
        4 Query  /* mysql-connector-java-5.1.20 (Revision: [email protected]) */SELECT @@session.auto_increment_increment 
        4 Query  SHOW COLLATION 
150528 20:22:55  4 Query  SET NAMES latin1 
        4 Query  SET character_set_results = NULL 
        4 Query  SET autocommit=1 
        4 Query  SET sql_mode='STRICT_TRANS_TABLES' 
        4 Query  SET autocommit=0 
        4 Query  SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED 
150528 20:23:08  4 Query  INSERT INTO pub_tair_germplasm(
    germplasm_id, 
    name, 
    original_name, 
    sp_growth_conditions, 
    description, 
    description_uc, 
    is_mutant, 
    is_aneuploid, 
    ploidy, 
    species_variant_id, 
    taxon_id, 
    aneuploid_chromosome, 
    date_entered, 
    date_last_modified, 
    tair_object_id, 
    is_obsolete, 
    tair_object_type_id, 
    germplasm_type) 
VALUES (
    500689369, 
    'CS2000002', 
    'CS2000002', 
    'none', 
    'Sequence-indexed T-DNA insertion line; from the GABI-Kat project (German Plant Genomics Program - Koelner Arabidopsis T-DNA lines); generated using flanking sequence tags (F 
STs) in the Columbia (Col-0) background; genomic DNA was isolated from T1 plants; plant sequences adjacent to T-DNA borders were amplified by adapter-ligation PCR; automated pur 
ification and sequencing of PCR product were conducted followed by computational trimming of the resulting sequence files; for details, see the GABI-Kat web site: http://www.gab 
i-kat.de; this is a T4 generation single-plant line potentially homozygous for the insertion. May be segregating for phenotypes that are not linked to the insertion; may have ad 
ditional insertions potentially segregating.', 
    'SEQUENCE-INDEXED T-DNA INSERTION LINE; FROM THE GABI-KAT PROJECT (GERMAN PLANT GENOMICS PROGRAM - KOELNER ARABIDOPSIS T-DNA LINES); GENERATED USING FLANKING SEQUENCE TAGS (F 
STS) IN THE COLUMBIA (COL-0) BACKGROUND; GENOMIC DNA WAS ISOLATED FROM T1 PLANTS; PLANT SEQUENCES ADJACENT TO T-DNA BORDERS WERE AMPLIFIED BY ADAPTER-LIGATION PCR; AUTOMATED PUR 
IFICATION AND SEQUENCING OF PCR PRODUCT WERE CONDUCTED FOLLOWED BY COMPUTATIONAL TRIMMING OF THE RESULTING SEQUENCE FILES; FOR DETAILS, SEE THE GABI-KAT WEB SITE: HTTP://WWW.GAB 
I-KAT.DE; THIS IS A T4 GENERATION SINGLE-PLANT LINE POTENTIALLY HOMOZYGOUS FOR THE INSERTION. MAY BE SEGREGATING FOR PHENOTYPES THAT ARE NOT LINKED TO THE INSERTION; MAY HAVE AD 
DITIONAL INSERTIONS POTENTIALLY SEGREGATING.', 
    CASE null WHEN 'F' THEN 'n' WHEN 'T' THEN 'y' ELSE 'y' END, 
    CASE 'F' WHEN 'F' THEN 'n' WHEN 'T' THEN 'y' ELSE 'y' END, 
    '2', 
    null, 
    1, 
    null, 
    '2015-01-06 10:49:21', 
    '2015-01-06 10:40:55', 
    6530679980, 
    'F', 
    200016, 
    'individual_line') 

Проблема остается неизменной.

+1

'innodb_buffer_pool_size' не имеет значения для таблиц с использованием механизма хранения MEMORY; за исключением того, что память, выделенная пулу буферов InnoDB, уменьшает объем доступной памяти для других процессов. При фиксированной длине строки 6407+ байтов 68 000 строк составляют около 415 МБ. Есть ли еще сеанс, удерживающий блокировку на столе? – spencer7593

+0

См. Правки; нет замков. –

+1

Есть ли монитор в/из инструмента Clover/ETL? Механизм хранения MEMORY * отличается * от механизма хранения InnoDB. Механизм хранения MEMORY не поддерживает транзакции, блокировки находятся на уровне таблицы. Я не понимаю, какую информацию вы бы хотели получить от вывода монитора InnoDB. Я думаю, что вместо этого вы собрали вывод из 'SHOW FULL PROCESSLIST' и, возможно, * временно * включили общий журнал (' SET GLOBAL general_log = 1'), общий файл журнала может стать действительно очень быстрым, поэтому не забудьте оставьте это включенным. Также обратите внимание на журнал ошибок MySQL. – spencer7593

ответ

1

Ну, я не знаю, в чем проблема была конкретно, но загрузите версию с разделителями табуляции данные на сервер mysql и делают это:

LOAD DATA LOCAL INFILE '/tmp/pub_tair_grm_insert.csv' INTO TABLE pub_tair_germplasm; 
Query OK, 68932 rows affected, 65535 warnings (1.26 sec) 
Records: 68932 Deleted: 0 Skipped: 0 Warnings: 6 

, очевидно, ответ, независимо от его вопроса. Должно быть что-то в доработке JDBC выполняется Clover/ETL, что резко замедляет вставки. Я посмотрю, что если у меня появится шанс, но сейчас LOAD дает мне то, что мне нужно.

0

Я подозреваю, что вы пытаетесь превысить максимальный размер, разрешенный для таблицы, используя механизм хранения MEMORY. Но я не понимаю, почему ошибка не возвращается MySQL, или Clover/ETL не возвращает ошибку или не отключается.

Я рекомендую вам собрать выход из

SHOW FULL PROCESSLIST 

Чтобы увидеть состояние текущих сессий. Может быть, заявление INSERT «висит»?

Вы можете также временно включить общий журнал

SET GLOBAL general_log = 1 

А потом попробуйте нагрузку. Этот файл журнала может расти действительно очень быстро, поэтому вы хотите, чтобы он был установлен на 0, чтобы отключить его.

Как я отметил в своем комментарии, я вычисляю размер более 415 МБ для таблицы. Это основано на использовании движка MEMORY (строки фиксированной длины), размер строки 6407 байт (при условии, что один байтовый набор символов для столбцов символов), не считая накладных расходов на строки для нулевых индикаторов.

Выдержка из Справочного руководства по MySQL, раздел 15.3 ПАМЯТЬ Хранение двигателя

Максимальный размер таблиц памяти ограничен системной переменной max_heap_table_size, который имеет значение по умолчанию 16Мб. Чтобы обеспечить соблюдение ограничений по размеру для таблиц MEMORY, измените значение этой переменной. Значение эффекта для CREATE TABLE или последующего ALTER TABLE или TRUNCATE TABLE, это значение, используемое для жизни таблицы. Перезапуск сервера также устанавливает максимальный размер существующих таблиц MEMORY для глобального значения max_heap_table_size. Вы можете установить размер для отдельных таблиц, как описано далее в этом разделе.

Ссылка: https://dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html


Кроме того, отметим, что двигатель MEMORY хранения не поддерживает транзакции.

Если у вас есть требование, что никакие другие сеансы не видят данные, пока он в процессе загрузки, вы могли бы рассмотреть вопрос об использовании InnoDB или MyISAM и загрузки на имени таблицы разные, а затем переименовать таблицу, как только нагрузка завершено.

Или используйте механизм хранения InnoDB и транзакцию hughjass. Выполняйте все операции INSERT как часть одной транзакции. (Но я не поклонник этого подхода, я боюсь генерировать целую разбросанность отката.)

Или используйте механизм хранения MyISAM. Возьмите LOCK на столе, выполните все операции INSERT, а затем отпустите блокировку. (Но любые другие утверждения, пытающиеся ссылаться на таблицу, «зависают», ожидая освобождения блокировки.)

+0

Я увеличил память в max_heap_table_size и установил глобальный журнал, результаты были также отредактированы в основном описании с PROCESS_LIST. Никаких изменений в поведении. –

0

В широком смысле размер партии с 5000 операторами считается слишком большим. Фактический оптимальный размер партии JDBC зависит от нескольких критериев. Однако цифры от 50 до 100 должны быть в порядке. Вы можете попробовать еще большее количество конечностей и попытаться найти правильный номер для вас. Я определенно немного сыграю с номером и проверю, как меняется производительность с разными номерами.

Что касается требований к памяти (что также является одним из факторов, возникающих при использовании размера партии), кажется, что на основе оператора CREATE максимальный размер строки составляет 6418 байт. Поэтому, если у вас примерно 68 тыс. Строк (подсчет с максимальным размером такой строки), максимальная требуемая память для этой задачи составляет около 450 ГБ. То есть, однако, даже не половина из max_heap_table_size, которую вы определили. Поэтому не должно быть проблем, если таблица была пустой. Более того, если вы достигли предела в таблице MEMORY, график CloverETL завершился неудачей при соответствующем SQLException (java.sql.SQLException: The table <YOUR_MEMORY_TABLE>' is full). Однако, похоже, это не так.

Еще одна возможность, которая приходит мне на ум (и снова связана с вышеупомянутыми примечаниями), состоит в том, что на самом деле у вас недостаточно доступной памяти для хранения ваших данных в памяти, и поэтому данные обмениваются на диске. Это может прояснить замедление производительности. Если вы, однако, исчерпали всю доступную виртуальную память (ОЗУ и своп), скорее всего, вы столкнетесь с другой проблемой с разными симптомами - так что это не так.

Возможно, если ничего не помогает, вы можете поделиться с нами журналом из выполнения графика CloverETL (если это возможно, выполняется на уровне журнала DEBUG), чтобы мы могли увидеть, есть ли что-нибудь подозрительное. Кроме того, коммерческая версия CloverETL поставляется также с MySQLDataWriter, который использует собственный клиент MySQL и, возможно, может решить проблемы, связанные с JDBC. Я бы начал с поиска нужного размера партии.

+0

Я пробовал размер партии 100 и 50, единственное различие заключалось в том, что журналы показывали движение вместо того, чтобы сидеть без изменений для большей партии. Количество записей в секунду не изменилось на 24 для обеих настроек. –

+0

Сервер имеет много свободной памяти. У загрузчика MySQL нет проблем с загрузкой всех записей менее чем за 2 секунды. –

+0

Я буду запускать график под отладкой и посмотреть, что выйдет. В журналах пока нет ошибок, мы увидим, что выйдет в отладке. –

Смежные вопросы