Мы используем Python и LOAD DATA INFILE для загрузки данных из CSV в нашу промежуточную базу данных. Начиная с этапа, у нас есть sql-скрипты, перемещающие данные в нашу фактическую производственную базу данных.MySQL insert with sub select slow
LOAD DATA INFILE молниеносно по сравнению с выбором рядов от постановки и вводом их в производство.
Мы на 5,7, используя InnoDB и мы применили следующую конфигурацию, чтобы оптимизировать наши вставки:
- Набор innodb_autoinc_lock_mode до 2
- Установить размер InnoDB пул буферов на половину памяти (16 Гб)
- Установите размер буфера для журнала до 4 ГБ
- Мы используем ОПЕРАЦИИ
- Использовать SET autocommit = 0;
Все еще вставка из одной таблицы в другую значительно медленнее по сравнению с LOAD DATA INFILE.
Когда я смотрю на записи ввода-вывода, с данными загрузки данных он достигает до 30 МБ/с, тогда как с обычными вставками максимальный 500 КБ/с.
Есть ли способ улучшить эту производительность или нам нужно полностью пересмотреть наш подход. Я могу думать об использовании OUTFILE для вспомогательных запросов и загружать их обратно с помощью INFILE, но это не похоже на правильный подход.
И заявление:
INSERT INTO documentkey (documentClassCode,dId,fileTypeCode,internet,pathId,creationTime,signature,CSVimportId)
SELECT case when csv.`Document Class` is null
then (select classCode from mydb.class where classDesc = 'Empty'
And LookupId = (select LookupId from mydb.Lookup where LookupGroupCode = 'C' and EntityLookedup = 'documentkey')
)
else (select classCode from mydb.class where classDesc = csv.`Document Class`
And LookupId = (select LookupId from mydb.Lookup where LookupGroupCode = 'C' and EntityLookedup = 'documentkey')
)
end,
csv.`dId`,
(select typeCode from mydb.type
Where typeDesc = csv.`File Type`
And LookupId = (select LookupId from mydb.Lookup where LookupGroupCode = 'T' and EntityLookedup = 'documentkey')
),
case when csv.`message ID` is null
then (select messageIncrId from message where internetdesc = 'Empty')
else case when exists (select internetMessageIncrId from internetMessage where internetdesc = csv.`Internet Message ID`)
then (select internetMessageIncrId from internetMessage where internetdesc = csv.`Internet Message ID`)
else 0
end
end,
case when exists (select pathId from Path where pathDesc = csv.`path`)
then (select pathId from Path where pathDesc = csv.`path`)
else 0
end,
case when csv.`Creation Time` <> '' then STR_TO_DATE(csv.`Creation Time`, '%d/%m/%Y %H:%i:%s') else '2016-06-16 10:00:00' end,
#STR_TO_DATE(csv.`Creation Time`, '%Y-%m-%d %H:%i:%s'),
csv.`Signature Hash`,
1
#csv.`CSV import id`
FROM `mydb_stage`.`csvDocumentKey` csv
where csv.`dId` is not null and csv.threadId = @thread;
Выберите часть запроса занимает лишь доли секунды.
Объясните:
'1', 'PRIMARY', 'csv', NULL, 'ALL', NULL, NULL, NULL, NULL, '1', '100.00', 'Using where'
'12', 'DEPENDENT SUBQUERY', 'path', NULL, 'eq_ref', 'pathDesc_UNIQUE', 'pathDesc_UNIQUE', '1026', 'func', '1', '100.00', 'Using where; Using index'
'11', 'DEPENDENT SUBQUERY', 'path', NULL, 'eq_ref', 'pathDesc_UNIQUE', 'pathDesc_UNIQUE', '1026', 'func', '1', '100.00', 'Using where; Using index'
'10', 'SUBQUERY', 'message', NULL, 'const', 'messageDesc_UNIQUE', 'messageDesc_UNIQUE', '2050', 'const', '1', '100.00', 'Using index'
'9', 'DEPENDENT SUBQUERY', 'message', NULL, 'eq_ref', 'messageDesc_UNIQUE', 'messageDesc_UNIQUE', '2050', 'func', '1', '100.00', 'Using where; Using index'
'8', 'DEPENDENT SUBQUERY', 'message', NULL, 'eq_ref', 'messageDesc_UNIQUE', 'messageDesc_UNIQUE', '2050', 'func', '1', '100.00', 'Using where; Using index'
'6', 'DEPENDENT SUBQUERY', 'type', NULL, 'eq_ref', 'typeDesc_UNIQUE', 'typeDesc_UNIQUE', '1026', 'func', '1', '100.00', 'Using index condition; Using where'
'7', 'SUBQUERY', 'Lookup', NULL, 'ref', 'PRIMARY', 'PRIMARY', '6', 'const', '3', '10.00', 'Using where'
'4', 'SUBQUERY', 'class', NULL, 'const', 'classDesc_UNIQUE', 'classDesc_UNIQUE', '1026', 'const', '1', '100.00', NULL
'5', 'SUBQUERY', 'Lookup', NULL, 'ref', 'PRIMARY', 'PRIMARY', '6', 'const', '2', '10.00', 'Using where'
'2', 'DEPENDENT SUBQUERY', 'class', NULL, 'eq_ref', 'classDesc_UNIQUE', 'classDesc_UNIQUE', '1026', 'func', '1', '20.00', 'Using index condition; Using where'
'3', 'SUBQUERY', 'Lookup', NULL, 'ref', 'PRIMARY', 'PRIMARY', '6', 'const', '2', '10.00', 'Using where'
Одна из причин 'LOAD DATA' - это быстро, потому что на самом деле это не делает какой-либо материал базы данных, тогда как' INSERT'. –
@TimBiegeleisen Я предполагаю, что он работает с определенными настройками конфигурации, которые являются прозрачными для пользователя, и я бы предположил, что вы могли бы достичь аналогичной конфигурации и, следовательно, производительности для INSERT. Это просто вопрос о том, как. – L4zl0w
Как вы выбираете и вставляете данные. вы можете показать нам запрос –