大型数据集的排序无法完成
Posted
技术标签:
【中文标题】大型数据集的排序无法完成【英文标题】:Sorting of large dataset fails to complete 【发布时间】:2011-04-13 20:30:08 【问题描述】:这是debugging a mysql insert fail in php 的后续行动,因为我现在有时间继续这个项目。
我在这个问题中有三个表: 海报数据中有 840,721 张海报 海报类别中有 58,506 个海报类别 poster_prodcat 中的 17,629,007(1700 万+)张海报/类别组合
根据 Yahoo! 的 Efficient Pagination 演示文稿,我正在尝试向 poster_prodcat 添加一个类别排名编号,以便我们可以按排名分页,而不是使用限制和偏移量。尽管将我的 php mysql 连接超时设置为 3600(我知道这很疯狂)并关闭了 php 超时,但排序似乎永远不会完成。可能是几十到十万左右,但绝不是完整的 17,000,000 集。
这是脚本:
$sql1="select distinct apcatnum from poster_prodcat";
$result1 = mysql_query($sql1);
while ($cats = mysql_fetch_array ($result1))
$sql2 = "SELECT poster_data.apnumber,poster_data.aptitle
FROM poster_prodcat,poster_data
WHERE poster_prodcat.apcatnum ='$cats[apcatnum]'
AND poster_data.apnumber = poster_prodcat.apnumber
ORDER BY aptitle ASC";
$result2 = mysql_query($sql2);
$ordernum=1;
while ($order = mysql_fetch_array ($result2))
$sql3 = "UPDATE poster_prodcat SET catorder='$ordernum'
WHERE apnumber='$order[apnumber]' AND apcatnum='$cats[apcatnum]'";
$result3 = mysql_query($sql3);
$ordernum++;
这是在同时托管该站点的 2 gig 服务器上。超时时间很长,服务器没有崩溃,所以我看不出是什么阻止了它完成。我可以在这台服务器上执行此操作吗,或者由于这是每月一次左右的操作,我是否应该创建一些内存大的 EC2 实例,在那里进行排序并下载按摩表?
谢谢。
这是 poster_data 的结构(删除了一些不参与选择的字段):
CREATE TABLE `poster_data` (
`apnumber` mediumint( 8 ) NOT NULL DEFAULT '0',
`aptitle` varchar( 255 ) NOT NULL DEFAULT '',
`aptype` varchar( 100 ) NOT NULL DEFAULT '',
[snip]
UNIQUE KEY `posterid` ( `apnumber` ) ,
KEY `aptitle` ( `aptitle` ) ,
KEY `aptype` ( `aptype` ) ,
KEY `title_type` ( `aptitle` , `aptype` ) ) ENGINE = InnoDB;
poster_prodcat:
CREATE TABLE `poster_prodcat` (
`apcatnum` mediumint( 8 ) NOT NULL DEFAULT '0',
`apnumber` mediumint( 8 ) NOT NULL DEFAULT '0',
`catorder` mediumint( 7 ) NOT NULL DEFAULT '0',
PRIMARY KEY ( `apcatnum` , `apnumber` ) ,
KEY `apcatnum` ( `apcatnum` ) ,
KEY `apnumber` ( `apnumber` ) ,
KEY `catorder` ( `catorder` )
) ENGINE = InnoDB /*!50100 PARTITION BY HASH (apcatnum) PARTITIONS 10 */;
【问题讨论】:
向我们展示您的查询计划和表格 ddl 创建脚本。 @Chris Buckler:需要更新才能按类别将排名数字添加到海报数据中。所以是的,每条记录都需要更新。同样,每月只在下载新数据时执行一次。 @Ian - 刚刚用 200 万条记录尝试过这样的事情,只需要大约 15 秒。我认为您可能会陷入无限循环或其他问题。当计数器在 250k、1M、5M 时,你能把它输出吗?只是为了确保它不会被挂断... 删除 ORDER BY 对时间有影响吗? @Chris Buckler:我想知道是不是因为 2 gig 服务器也在运行 Web 服务器和邮件,所以缺少关键缓冲区大小而需要这么长时间。这三个 inno 表(我仅有的三个 inno 表)的数据大小为 687.8M,缓冲池为 128.0M。很明显,这是一个非常棒的表现。将启动一个大型 EC2 实例一小时,看看是否需要几秒钟。 【参考方案1】: while ($order = mysql_fetch_array ($result2))
$sql3 = "UPDATE poster_prodcat SET catorder='$ordernum'
WHERE apnumber='$order[apnumber]' AND apcatnum='$cats[apcatnum]'";
$result3 = mysql_query($sql3);
$ordernum++;
这是否意味着您正在执行 1700 万次单独的交易?如果每秒能承受一千笔交易,光这部分就需要 5 个小时左右吧?
***(随时可用,但不是我认为的权威)关于innodb transactions 的说法。
在完全符合 ACID 的条件下运行时 模式下,InnoDB 必须刷新到磁盘 不过,每笔交易至少一次 它将结合插入的冲洗 从多个连接。对于典型的 旋转硬盘驱动器或阵列,这 将施加约200的限制 每秒更新事务。
【讨论】:
是的,当我运行 EC2 服务器只是为了处理这个问题时,它花了几个小时。想不出更好的方法来处理这个问题。 @Ian:我查找了“Yahoo! 的高效分页演示文稿”并找到了这个网址:slideshare.net/Eweaver/efficient-pagination-using-mysql。我在那里看不到任何类似于您正在尝试做的事情。我在看正确的演示文稿吗? 第 页。 14 他们谈论使用另一种类型的订单值而不是“限制 M,N”对结果进行分页。就我而言,我正在为数千个类别创建订单值。 所以您正在创建一个新列来保存排序顺序,而不是像幻灯片中那样使用 id 编号,对吧?他们的方法可能会正常工作,但通过使用现有的 ID 号,他们不必更新 1700 万行。以上是关于大型数据集的排序无法完成的主要内容,如果未能解决你的问题,请参考以下文章