从大表中分块提取报告
Posted
技术标签:
【中文标题】从大表中分块提取报告【英文标题】:Extracting reports from big tables in chunks 【发布时间】:2019-06-26 17:12:43 【问题描述】:这个问题听起来有点笼统。仍然。 我们有一张包含数亿条记录的表。 为了制作报告,其他几个较小的表正在与之连接。 为所有适当的列创建索引。 客户希望获得一份超过一年的报告,可能多达 1 亿行。
为了保证进程的安全,假设脚本终止,或者与数据库的连接断开,报告必须以块的形式提取,以便下一个进程在前一个终止的地方提取报告。
问题是报告可以按 varchar/int 列排序,其中可以包含客户姓名、帐号、不同格式的各种个人数据等,我还没有整理出如何获得合理数量的在这些情况下,每个块的行(比如 ~50k)。
使用限制 x,y 将花费太多的数据量。 没有归档表,没有分区,数据不会聚合到单独的表中。一个表中只有一大块数据。
是否有既定的(魔术?)方法来处理这类问题?
【问题讨论】:
你能发布查询和查询的解释吗?还有,如果不是太问,schema呢? 您是否尝试过使用无缓冲查询或带有 PDO 的 ID 偏移量? 【参考方案1】:“有固定的(魔法?)方法来处理这类问题吗?” -- 你问的是我花了很多时间完善的几件事。
“数以亿计的记录...报告”和“报告可以按不同的列排序”——使用汇总表,可以更快地运行:http://mysql.rjweb.org/doc.php/summarytables。汇总表有助于排序。
“为所有适当的列创建索引”——对不起,我的玩世不恭,但我发现这个短语意味着你有一堆单列 INDEXes
,但还没有了解合适的 ' 的好处复合'索引。 http://mysql.rjweb.org/doc.php/index_cookbook_mysql 和 http://mysql.rjweb.org/doc.php/index1
“使用 LIMIT 和 OFFSET”——这就是它非常低效的原因:http://mysql.rjweb.org/doc.php/pagination。我认为不需要OFFSET
来解决您的问题。 “记住你离开的地方”可能有助于分块以最初构建汇总表。
“与 DB 的连接断开”——上述提示应使其足够快以避免此问题。如果不是,请提供SHOW CREATE TABLE
、SELECT
以及可能的其他详细信息。
"chunking" -- 以下是关于分块的提示,但我认为这不是解决当前问题的方法:http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks
“数以亿计的记录......在一个表中”——不是问题。我的提示是针对那个尺寸的。
“无分区”——很好。我不必花时间说服您分区不太可能有帮助:http://mysql.rjweb.org/doc.php/partitionmaint
你赢了。我想我从来没有指着我的 6 个博客来回答一个问题。
【讨论】:
我们没有汇总数据的汇总表。我们确实需要某种数据仓库,但每次提出问题时,答案都是“很快”。我们确实有复合索引。当按 varchar 列排序时,记住我们离开的位置并不容易,它不再是递增的 id,因此如果我们记住最后几个字符并进行比较,块的大小可能会有很大差异。考虑到这一切,我们决定改变手头的任务,排序将按 id 进行,我们将仅使用 id 键进行排序。谢谢你的提示,博客也不错! @ChungaChanga - 重新块大小变化......其中一个博客谈到使用LIMIT 1000,1
来查找前 1000 行的停止位置。这使块大小保持不变,而不必担心密钥的分布。这对于单列索引很有效,但对于复合索引会变得更加混乱。但我有点解决这个问题。以上是关于从大表中分块提取报告的主要内容,如果未能解决你的问题,请参考以下文章