【问题标题】:SELECT only a certain set of rows at a time一次只选择一组特定的行
【发布时间】:2011-01-26 14:42:30
【问题描述】:

我需要从一个表中选择数据并将其插入到另一个表中。目前 SQL 看起来像这样:

   INSERT INTO A (x, y, z)
   SELECT x, y, z
   FROM B b
   WHERE ...

但是,SELECT 非常庞大,导致超过 200 万行,我们认为它占用了太多内存。 Informix(本例中的 db)在运行查询时会耗尽虚拟内存。

我将如何选择和插入一组行(比如 2000 年)?鉴于我认为没有任何行 ID 等。

【问题讨论】:

  • 试试FIRST; LIMIT 是支持 10+ 的同义词:publib.boulder.ibm.com/infocenter/idshelp/v10/index.jsp?topic=/…
  • 是的,将其与skip 结合使用,您可以循环遍历整个集合。(如果您知道总行数
  • 如果表 B 发生变化,您不会冒着跳过未复制的行的风险吗?我知道我没有提到表 B 可以更改,在我的情况下可能不会更改,但我只是在这里大声思考。

标签: sql database select informix


【解决方案1】:

您可以从表中执行 SELECT FIRST n *。其中 n 是您想要的行数,例如 2000。此外,在 WHERE 子句中执行嵌入式选择,检查您要插入的表中是否存在已存在的行。这样下次运行该语句时,它就不会包含已插入的数据。

【讨论】:

  • 这听起来不错。您将如何编写一个循环直到选择不返回任何行的选择循环?
  • 使用 NOT EXISTS 函数确保您插入的行在新表中不存在。
【解决方案2】:

我假设您有一些执行此操作的脚本?只要您对从嵌套选择返回的值进行排序,您就可以循环和限制。这是一些伪代码。

total = SELECT COUNT(x) FROM B WHERE ...
while (total > 0) 
  INSERT INTO A (x, y, z) SELECT x, y, z FROM B b WHERE ... ORDER BY x LIMIT 2000
  total = total - 2000
end

【讨论】:

    【解决方案3】:

    我几乎可以肯定 IDS 只允许您使用 FIRST 子句将数据返回给客户端1,这是您希望尽可能避免的事情。

    你说你得到一个内存不足错误(而不是一个长事务中止错误)?您是否查看过服务器的配置以确保其具有合理的内存量?

    这部分取决于您的数据集有多大,以及约束是什么——为什么要跨表进行加载。但我通常的目标是确定一种将数据划分为可加载子集并在循环中按顺序运行这些子集的方法。例如,如果序列号在 1 到 10,000,000 之间,我可能会运行循环十次,条件是序列号为 AND seqnum >= 0 AND seqnum < 1000000' and thenAND seqnum >= 1000000 AND seqnum

    这有点麻烦,并且您希望在范围大小方面犯错(更多的小分区而不是更少的大分区 - 以减少内存不足的风险)。


    1 稍微过度简化。例如,存储过程必须算作“客户端”,并且存储过程中的通信成本(很多)低于访问真正客户端的成本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-26
      • 2016-02-17
      • 2016-10-12
      • 2017-06-19
      • 1970-01-01
      相关资源
      最近更新 更多