iSeries查询更改了子查询结果行的选定RRN

时间:2014-03-19 22:07:13

标签: sql db2 ibm-midrange db2-400

我正在尝试为可以包含数百万行(每月最多300万行)的iSeries数据库表进行最佳SQL查询。我每行唯一的关键是它的RRN(相对记录号,即行的物理记录号)。

我的目标是将表格与另一个小表格连接,以便为我提供其中一个数字列的文字说明。但是,涉及的行数可能超过200万,这通常会导致查询因内存不足而失败。所以我想重写查询以避免与任何其他表连接大的子集。因此,想法是在给定月份内选择单个页面(最多30行),然后 将该子集连接到第二个表。

然而,我遇到了一个奇怪的问题。我使用以下查询来检索我想要的页面行的RRN:

    select t.RRN2    -- Gives correct RRNs
    from (
      select row_number() over() as SEQ,
        rrn(e2) as RRN2, e2.*
      from TABLE1 as e2
      where e2.UPDATED between '2013-05-01' and '2013-05-31'
      order by e2.UPDATED, e2.ACCOUNT
    ) as t
    where t.SEQ > 270 and t.SEQ <= 300    -- Paging
    order by t.UPDATED, t.ACCOUNT

这个查询工作得很好,为我需要的行返回正确的RRN。但是,当我尝试将子查询的结果与另一个表连接时, RRN已更改。所以我将查询简化为简单外部查询中的子查询,没有任何连接:

select rrn(e) as RRN, e.*
  from TABLE1 as e
  where rrn(e) in (
    select t.RRN2    -- Gives correct RRNs
    from (
      select row_number() over() as SEQ,
        rrn(e2) as RRN2, e2.*
      from TABLE1 as e2
      where e2.UPDATED between '2013-05-01' and '2013-05-31'
      order by e2.UPDATED, e2.ACCOUNT
    ) as t
    where t.SEQ > 270 and t.SEQ <= 300    -- Paging
    order by t.UPDATED, t.ACCOUNT
  )
  order by e.UPDATED, e.ACCOUNT

外部查询使用RRN作为行键,简单地抓取子查询选择的每一行的所有列。但是这个查询不起作用 - 它返回具有完全不同的RRN的行。

我需要实际的RRN,因为它将用于在后续查询中从表中检索更详细的信息。

关于为什么RRN最终不同的任何想法?

解决

我决定将查询分成两个调用,一个是发出简单的子查询,只返回RRN(rows-IDs),第二个是执行其余的JOIN,依此类推,检索每个查询的完整信息。行。 (由于表每天只更新一次,并且行永远不会被删除,因此无需担心潜在的时间问题。)

这种方法看起来效果很好。

附录

关于为什么会发生内存不足错误的问题,这似乎仅限于我们测试服务器的部分。有些只能处理大约2米的行,而有些则可以处理更多。所以我猜这是管理员在逐个服务器的基础上施加的某种限制。

3 个答案:

答案 0 :(得分:4)

我觉得很难相信查询一个只有300万行的表,即使加入了其他内容,也会导致内存不足,所以在我看来你应该首先解决这个问题(或者引起它待解决)。

关于为什么RRN最终不同的问题,我将自由引用the manual

  

如果参数标识了从多个基表派生的视图,公用表表达式或嵌套表表达式,则该函数返回视图的外部子选择中的第一个表的相对记录号,公用表表达式,或者嵌套表表达式。

...where something in (select somethingelse...)类型的构造通常会转换为连接,因此存在。

答案 1 :(得分:4)

尝试使用RRN作为主键是在寻找麻烦。

我发现很难相信没有钥匙可用。

当然,表中可能没有定义明确的主键。但是表中是否有一个唯一的键?

表中可能没有定义任何键(一种20yrs过时的做法),但在这种情况下,通常会有一个逻辑文件,其中定义了一个唯一键,应用程序将其作为事实上的主键。桌子。

尝试通过绿屏(DSPDBR)或GUI(通过“显示相关”)查找相关对象。键控逻辑文件在GUI中显示为视图。因此,您需要查看属性以确定它们是否是唯一键控的DDS逻辑而不是非键控SQL视图。

有几次我遇到了没有事实上的主键的表。通常,可以确定现有列中可以定义的内容。

如果确实没有PK,我只需添加一个。通常是生成的标识列。您可以使用一种技术轻松添加列,而无需重新编译或测试任何传统的RPG / COBOL程序。 (并注意LVLCHK(* NO)不是它!)

该技术在现代化红皮书的第4章中列出 http://www.redbooks.ibm.com/abstracts/sg246393.html

1)将数据移动到新的PF(或SQL表) 2)使用现有PF的名称创建新的LF 3)将现有LF重新命名为新PF(或SQL表)

正确完成后,现有对象的记录格式标识符不会更改,因此您无需重新编译任何RPG / COBOL程序。

答案 2 :(得分:1)

除非您可以专门控制它,例如,通过ALDSCPDDTA(* NO)用于STRSQL,否则SQL可以为任何中间行集创建结果行的副本。 RRN()函数总是访问物理记录号,与ROW_NUMBER()函数相反,后者返回一个逻辑行号,表示有序(或无序)行集中的相对位置。如果生成副本,则无法保证RRN()保持一致。

其他考虑随着时间的推移而适用;但在这种情况下,将中间结果行简单地复制为任何东西都是可能的。