我正在查询一些非常大的表格(TargetTable),并且有一个特定的过程,在其第二次迭代中被卡住,永远不会完成也不会崩溃。无论范围的开始(loopIndex)还是范围的大小(loopStepShort)如何,第一次迭代总是在几分钟内完成。
期待听到您的想法和建议。
[更新1] 如果我执行以下操作之一,问题就会消失:
- 删除内部连接的嵌套部分;
- 使用内存临时表格来处理内部连接的嵌套部分(感谢@SashaPachev);
- 在while循环之外运行每个循环迭代;
- 使用更小的TargetTable。
[更新2] 已解决! 我认为问题可能出现在将一些数据库索引复制到数据库转换过程中时未被复制。因为当我尝试重现一个例子时,它仅发生在未索引的表上(高CPU使用率和几乎无限的循环步骤)MariaDB Server,JIRA。
MySQL InnoDB引擎(10.0.21-MariaDB Server,Linux x86_64,Fedora v.21)的自定义配置如下:
innodb_buffer_pool_size = 2G
net_write_timeout = 1800
net_read_timeout = 1800
join_buffer_size = 2G
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 4M
max_allowed_packet = 4G
key_buffer = 2G
sort_buffer_size = 512K
程序主体如下所示:
SET loopIndex = 0;
SET loopMax = 20000000;
SET loopStepShort = 10000;
WHILE loopIndex < loopMax do
UPDATE TargetTable AS t0,
(SELECT __index, sessionStartAge
FROM SubjectTable AS t0
INNER JOIN (SELECT t0.id, t0.admission,
if(t0.startage is null and t0.endage is null, 21,
if(least(t0.startage, t0.endage) <= 1, 1,
if(least(t0.startage, t0.endage) <= 4, 2,
if(least(t0.startage, t0.endage) <= 9, 3,
if(least(t0.startage, t0.endage) <= 14, 4,
if(least(t0.startage, t0.endage) <= 19, 5,
if(least(t0.startage, t0.endage) <= 24, 6,
if(least(t0.startage, t0.endage) <= 29, 7,
if(least(t0.startage, t0.endage) <= 34, 8,
if(least(t0.startage, t0.endage) <= 39, 9,
if(least(t0.startage, t0.endage) <= 44, 10,
if(least(t0.startage, t0.endage) <= 49, 11,
if(least(t0.startage, t0.endage) <= 54, 12,
if(least(t0.startage, t0.endage) <= 59, 13,
if(least(t0.startage, t0.endage) <= 64, 14,
if(least(t0.startage, t0.endage) <= 69, 15,
if(least(t0.startage, t0.endage) <= 74, 16,
if(least(t0.startage, t0.endage) <= 79, 17,
if(least(t0.startage, t0.endage) <= 84, 18,
if(least(t0.startage, t0.endage) <= 89, 19,
if(least(t0.startage, t0.endage) <= 120, 20, 21))))))))))))))))))))) AS sessionStartAge
FROM SubjectTable AS t0
INNER JOIN ids AS t1 ON t0.id = t1.id
AND t1.id >= loopIndex
AND t1.id < (loopIndex + loopStepShort)
GROUP BY t0.id, t0.admission) AS t1
ON t0.id = t1.id AND t0.admission = t1.admission) AS t1
SET t0.sessionStartAge = t1.sessionStartAge
WHERE t0.__index = t1.__index;
SET loopIndex = loopIndex + loopStepShort;
END WHILE;
最后,以下是表格的大致尺寸:
- 表格:ids:
- 表行数:约1,500,000条记录,
- 数据长度:约250 MB,
- 索引长度:约140 MB,
- 表格大小:约400 MB
- 表格:TargetTable:
- 表行数:约6,500,000条记录,
- 数据长度:约4 GB,
- 索引长度:约350 MB,
- 表格大小:约4.35 MB
- 表格:SubjectTable:
- 表行数:约6,500,000条记录,
- 数据长度:约550 MB,
- 索引长度:N/A,
- 表格大小:约550 MB
非常感谢您的帮助。
我想我需要向Oracle/MariaDB提出一个错误报告,并更新这篇文章。