MySQL 从 left & Right Join 的结果插入导致内存问题

MySQL Insert from results of left & Right Join results in memory issue

我在 运行 2 个大 table 上的插入查询时遇到问题。一个table是6700万,一个是10万。我正在尝试在 2 table 上进行 LEFT 和 RIGHT Join,并将结果放入另一个 table。该查询在 1M 条目下的较小 tables 上运行完美。但是当进入更高的条目时,它会爆炸。我收到此错误:

Incorrect key file for table 'C:\Windows\TEMP\#sql3838_2_6.MYI'; try to repair it

在线阅读解决方案后,他们说要增加 mysql 使用的内存及其索引键。我已经尝试过了,但仍然遇到同样的问题。我现在不确定这是 mysql 的错误配置还是条形查询。

所以我真的在寻找优化我的查询的解决方案,以提高内存效率或更改 my.config 来处理查询。或者将查询拆分为 2 个不同的插入???那会有帮助吗?

MySQL 查询

INSERT INTO schema.orphan_results (_Doc_ID, Orphan_Entries, Entries_Table, Orphan_File) 
    SELECT C.A__Doc_ID, C.A_File, C.A_Table, C.B_File 
    FROM( SELECT A._Doc_ID AS A__Doc_ID, A.File AS A_File, A.Table AS A_Table, B.File AS B_File 
    FROM schema.Temp_Entries A 
    LEFT JOIN schema.temp_dir_scan B ON A.File = B.File 
    UNION SELECT A._Doc_ID as A__Doc_ID, A.File AS A_File, A.Table AS A_Table, B.File AS B_File 
    FROM schema.Temp_Entries A 
    RIGHT JOIN schema.temp_dir_scan B ON A.File = B.File) C 
WHERE C.A_File IS NULL OR C.B_File IS NULL

这里是 my.config MySql

default-storage-engine=INNODB
max_connections=800
query_cache_size=186M
table_cache=1520
tmp_table_size=900M
thread_cache_size=38
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=268M
key_buffer_size=1160M
read_buffer_size=128K
read_rnd_buffer_size=512K
sort_buffer_size=512K
innodb_additional_mem_pool_size=96M
innodb_buffer_pool_size=563M

我的系统

16 Gigs of Mem
52 Gigs of Free disk space.

错误消息通常是由于磁盘不足 space,但由于 52gigs 应该足够了(并且我假设您的文件系统可以处理 >2gb 的文件)它可能有所不同。

以下两件事应该可以限制所需的临时space:

  • 您应该为 temp_dir_scan.File 和 Temp_Entries.File 创建一个索引。

  • 您应该使用 "union all" 而不是 "union"(或者,如您建议的那样,拆分查询)。

您可以重写您的代码(不过,请创建索引):

INSERT INTO schema.orphan_results (_Doc_ID, Orphan_Entries, Entries_Table, Orphan_File) 
SELECT A._Doc_ID, A.File, A.Table, null 
FROM schema.Temp_Entries A 
where not exists (select 1 from schema.temp_dir_scan B where A.File = B.File)   
-- or a.file is null   -- you might need that if a.file can be null

INSERT INTO schema.orphan_results (_Doc_ID, Orphan_Entries, Entries_Table, Orphan_File) 
select null, null, null, B.File 
from schema.temp_dir_scan B 
where not exists (select 1 from schema.Temp_Entries A where A.File = B.File) 

由于 UNION 有一个内置的 distinct(虽然我不确定你是否知道),你可能想使用 select distinct A._Doc_ID ...,但如果你真的不需要它,不要!