MySQL:通过块检索大的选择

Tor*_*ren 17 mysql select save

我已经选择了更多

70万行

我想将所选数据保存到win2012 R2上的一个大型csv文件中

问:如何通过通道从MySQL中检索数据以获得更好的性能?

因为当我试图保存一个我得到的大选择

内存不足错误

Ed *_*bbs 33

您可以尝试使用该LIMIT功能.如果你这样做:

SELECT * FROM MyTable ORDER BY whatever LIMIT 0,1000
Run Code Online (Sandbox Code Playgroud)

你会获得前1000行.第一个LIMIT值(0)定义结果集中的起始行.它是零索引的,所以0表示"第一行".第二个LIMIT值是要检索的最大行数.要获得接下来的几组1,000,请执行以下操作:

SELECT * FROM MyTable ORDER BY whatever LIMIT 1000,1000 -- rows 1,001 - 2,000
SELECT * FROM MyTable ORDER BY whatever LIMIT 2000,1000 -- rows 2,001 - 3,000
Run Code Online (Sandbox Code Playgroud)

等等.当SELECT没有返回任何行时,你就完成了.

但这本身并不足够,因为在您一次处理1K行时对表进行的任何更改都会导致顺序失效.要及时冻结结果,首先将结果查询到临时表中:

CREATE TEMPORARY TABLE MyChunkedResult AS (
  SELECT *
  FROM MyTable
  ORDER BY whatever
);
Run Code Online (Sandbox Code Playgroud)

附注:确保事先不存在临时表是个好主意:

DROP TEMPORARY TABLE IF EXISTS MyChunkedResult;
Run Code Online (Sandbox Code Playgroud)

无论如何,一旦临时表到位,从那里拉出行块:

SELECT * FROM MyChunkedResult LIMIT 0, 1000;
SELECT * FROM MyChunkedResult LIMIT 1000,1000;
SELECT * FROM MyChunkedResult LIMIT 2000,1000;
.. and so on.
Run Code Online (Sandbox Code Playgroud)

我将留给你创建逻辑,计算每个块后的限制值并检查结果的结束.我还推荐比1000条记录更大的块; 这只是我从空中挑选的一个数字.

最后,在完成后删除临时表是一种很好的形式:

DROP TEMPORARY TABLE MyChunkedResult;
Run Code Online (Sandbox Code Playgroud)

  • @Aaron 使用 OFFSET 在大表中也无法使用。我在此类任务上投入了数月时间,唯一的解决方案是拥有一个可以手动完成的主数字键。"a 和 a+10000 之间的 id" a+=10000; 问题是 mysql 太愚蠢了,无法正确完成此类任务。它不记得任何内部指针,因此您无法从停止的地方继续。 (2认同)

pra*_*afi 11

LIMIT OFFSET当数据的大小非常大时,该方法会减慢查询速度。另一种方法是使用称为 Keyset 分页的东西。它需要在您的查询中使用唯一 id,您可以将其用作书签以指向上一页的最后一行。使用最后一个书签获取下一页。例如:

SELECT user_id, name, date_created
FROM users
WHERE user_id > 0
ORDER BY user_id ASC
LIMIT 10 000;
Run Code Online (Sandbox Code Playgroud)

如果上面的结果集返回带有user_idas的最后一行12345,您可以使用它来获取下一页,如下所示:

SELECT user_id, name, date_created
FROM users
WHERE user_id > 12345
ORDER BY user_id ASC
LIMIT 10 000;
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,您可以查看此页面