【问题标题】:How does 'IN' works in db2 sql query?'IN' 在 db2 sql 查询中如何工作?
【发布时间】:2017-11-29 18:25:06
【问题描述】:

我的要求是从 DB2 表中选择电话号码等于 16 组电话号码的数据。我尝试在我的本地测试数据上运行下面给出的这个查询,我的程序成功运行! 但是,当我尝试在真实表(备份表)上运行相同的程序时,我的 RUN jcl 因 S722 异常终止而失败。

我觉得这不是空间异常终止,因为我们正在使用具有 7 个圆柱体(1 个主要,6 个次要)属性的文件。根据我的研究,我发现带有'IN,'LIKE'的sql查询需要太多时间来执行,因此将Jobcard中的Time参数更改为NOLIMIT。但是没有运气!!

有人可以帮助我以其他方式编写此查询吗?或者帮我纠正这个问题....

这样查询:

EXEC SQL
DECLARE WS-CURSOR CURSOR WITH HOLD FOR
SELECT CUST_ID,CUST_NAME,SEQ_NUM,PHONE_NUM FROM PHONE_TAB 
  WHERE PHONE_NUM IN ('123456789','789456123','456789123','789456123' etc) AND
        PHONE_TYPE = 'DU' 
END-EXEC.

提前致谢!!

【问题讨论】:

  • 您的FETCH 是什么样的?我问的原因是失败不在声明中,即不可执行,S722 可能是数组大小问题。
  • PHONE_NUM 和 PHONE_TYPE 列的定义是什么?
  • 使用 JOBPARM LINES=999999。这应该让您在输出中写入所有行。顺便问一下,您期望有多少输出记录?而且我相信 Phone_type 应该在引号中作为“DU”。
  • @cschneid 你应该写一个答案,下面的其他答案都不正确
  • @SaggingRufus 我已将我的评论(现已删除)合并到答案中。希望这对未来的OP和其他人有所帮助。感谢您的提示,有时我在评论和回答之间摇摆不定。

标签: sql db2 mainframe


【解决方案1】:

Sx22 系列异常结束表示超出某些系统定义的参数。例如,S322 通常表示您已超出工作卡或工作步骤上 TIME 参数中的 CPU 时间量。

S722 异常结束表示您产生的阀芯输出量超过了您车间的 JES 参数所允许的数量。您需要确定该假脱机输出的来源以解决异常终止。

您可能有核心转储 (CEEDUMP)、已编码的调试输出(SYSOUT 或 SYSPRINT 或 STDOUT 或 STDERR),或已编码的失控报告 DD。 JESMSLGG DD 可以在 SDSF 输出的顶部或通过选择带有“?可能会向 S722 报告错误之前

也许您正在经历一个通向 S722 的S322。这是完全可能的,因为问题出现在大量数据上。

将时间参数设置为 NOLIMIT 是一种代价高昂的调试技术,因为大多数大型机商店都有适当的退款算法,通常 CPU 时间 = 预算中的金钱。您的商店可能有一个 JES 出口,专门用其他值代替 NOLIMIT 以防止其使用。

如 user6542823 所示,您可以添加 JOBPARM LINES=some-large-number 来绕过 S722,但您仍然必须解决根本问题。

z/OS 试图为您提供尽可能多的调试信息。充分利用它给你的东西。

鉴于...

  • 你说过你的程序在本地测试数据上执行得很好
  • 针对生产规模数据的备份运行时会出现问题

...那么 如果...

  • 您本地测试数据中表 PHONE_TAB 的定义与备份和生产数据中的定义匹配
  • 你的程序绑定成功
  • 您有权读取备份数据

...问题可能与您的 SQL 无关,而与数据量有关。

查看您的包裹的 EXPLAIN 输出,您可能会看到您正在扫描整个 PHONE_TAB 表。也许生产中存在一个索引,而您正在测试的备份中不存在该索引。

【讨论】:

    【解决方案2】:

    这是一个内联表连接,而不是执行 where in 子句

    IRL 我会将值放入临时表并加入临时表。但是例如我已经在线完成了。

    SELECT CUST_ID,CUST_NAME,SEQ_NUM,PHONE_NUM FROM PHONE_TAB
    
    join (
    values('123456789'),('789456123'),('456789123'),('789456123')
    ) as b (ph) on phone_num = ph
    
    where PHONE_TYPE = DU 
    

    两个表查询可能最快很难说,但对我来说,维护两个表肯定比每次运行时都创建一条 SQL 语句的程序更容易。

    SELECT CUST_ID,CUST_NAME,SEQ_NUM,PHONE_NUM FROM PHONE_TAB
    
    join look_tab b on phone_num = b.ph
    
    where PHONE_TYPE = DU 
    

    【讨论】:

    • ....这样做有明显的性能差异吗?我会(天真地)假设优化器会将它们全部转换为某种内存查找,计划应该是相同的。
    • IRL 在真实生活中,我将有两张表,一张是 phone_tab,一张是look_tab。 Look_tab 仅填充了我正在寻找的电话#,然后我将运行查询并检查索引器建议。有了两个表,您就会知道您总是有一个优化的查询,并且不必在每次运行查询时处理创建文本语句的细节。使用两张表我肯定会更快,因为您将使用推荐的索引等。
    • ....除非您使用的是小型临时表,否则这可能不适用。索引代表(更少)时间的空间权衡,并且至关重要的是,仍然有成本。优化器会忽略他们认为不能提供足够好处的索引。如果您的表(或临时结果集)足够小,优化器会将其放入内存中的工作集中并忽略您声明的任何索引(尽管它们可能对某些统计信息有用)。这也忽略了多次访问数据库(用于插入)和维护索引的成本。
    • @Clockwork-Muse 我相信电话号码上会有一个现有的索引。这是一年中相信的时候。
    • 哦,我不怀疑PHONE_TAB 上的索引是否存在(或应该存在),并且它将被使用。我不太确定的是 lookup 表上的索引将被使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多