MySQL插入子选择慢

时间:2016-06-17 10:47:50

标签: mysql performance innodb

我们正在使用Python和LOAD DATA INFILE将CSV中的数据加载到我们的临时数据库中。从暂存我们有sql脚本将数据移动到我们的实际生产数据库。

与从分段中选择行并将其插入生产中相比,

LOAD DATA INFILE快速闪烁。

我们在5.7,使用InnoDB,我们已应用以下配置来优化我们的插入:

  • 将innodb_autoinc_lock_mode设为2
  • 将innodb缓冲池大小设置为内存的一半(16GB)
  • 将日志缓冲区大小设置为4GB
  • 我们正在使用TRANSACTIONS
  • 使用SET autocommit = 0;

与LOAD DATA INFILE相比,从一个表到另一个表的插入仍然明显更慢。

当我查看IO写入时,加载数据infile会增加到30 MB / s,而使用普通插入时,它最高可达500KB /秒。

我们是否有办法改善这种表现,或者我们是否需要彻底重新思考我们的方法。我可以考虑使用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'

1 个答案:

答案 0 :(得分:1)

您没有提及为什么要改变您的方法,特别是如果您的主要目标是表现 SELECT 与在表中转储文件一样快,并且已经在MySQL文档中明确说明了 来自insert-speed

  

从文本文件加载表时,请使用LOAD DATA INFILE。这是   通常比使用INSERT语句快20倍。见章节   14.2.6,“LOAD DATA INFILE语法”。