是否建议在 Oracle 中循环执行查询与一次性执行查询以获得显着的性能提升?

Posted

技术标签:

【中文标题】是否建议在 Oracle 中循环执行查询与一次性执行查询以获得显着的性能提升?【英文标题】:Is executing query in loop vs in one go at Oracle recommended for substantial performance gain? 【发布时间】:2021-05-27 12:35:16 【问题描述】:

我有一个 Python 批处理作业,它根据提供的 ID 执行 SQL 查询。 id数一般在20k以上。

查询是:

SELECT MY_ID, COL_A, COL_B FROM SOME_TABLE WHERE ID IN dynamically_set_ids

由于 Oracle 将 IN 子句中的值数限制为 1000,因此我将查询更新为:

WITH ids_list AS 
(select id1 AS my_id FROM dual
UNION
select id2 AS my_id FROM dual ...) -- all 20k+ ids added like this
SELECT col_a,
       col_b,
       some_table.my_id

FROM   some_table
join   ids_list
ON     ids_list.my_id = some_table.my_id

上述查询在大约 33 分钟内执行。 但是当我循环 id 列表并循环执行查询时:

con = get_con()
for i in range(calculated_iterations):
    con.execute("select my_id, col_a, col_b where my_id in 0".format(1k_or_less_ids))
    # collect data

对于当前的数据量,上面的循环仅在大约 40 秒内返回预期数据。

所以,问题是:是否建议/可以在循环中执行选择?

由于工作在一夜之间运行,性能提升并不重要。 但是,为了获得这样的收益,是否会首选循环?

请注意,无法猜测数据量。它通常以数百万行运行。

【问题讨论】:

在什么情况下,您认为 33 分钟的任务比 40 秒的任务更可取? @ScottHunter 当我们想限制对数据库的访问时,我猜。 重复点击不到一分钟的总次数会比单次“点击”时间超过 30 倍的情况更糟吗? 【参考方案1】:

20K 'union select all ..' 语句?不管运行时性能如何,这就是疯狂的编码!

“教科书”的解决方案是将这 20k 值放在一个文本文件中,在其上定义一个外部表,然后

SELECT MY_ID, 
       COL_A, 
       COL_B 
FROM SOME_TABLE WHERE ID IN (select ext_id 
                             from my_external_table)
;

【讨论】:

您能否澄清一下从表中加载的 id 是否不会导致 ORA-01795 错误? 当然不是,阿达什。它们存储在 table 中,这与制作 IN 列表非常不同,例如in (1, 2, 4, 5, 20, 999, 1001, 20000)。那不是 “您能否澄清一下从表中加载的 id 是否不会导致 ORA-01795 错误?” “教科书式的解决方案”,会吗?如果您不相信我的话,那么您自己测试它会更容易和更快地编写 20k 'union select' 语句。这 20k 个 ID 最初来自哪里? 如果您没有使用外部表的权限或机器访问权限,您可以先将数据值(使用executeMany())上传到全局临时表之类的东西,然后使用该表在子查询中。在 WHERE IN 子句中使用多个值的一般参考是 cx-oracle.readthedocs.io/en/latest/user_guide/…

以上是关于是否建议在 Oracle 中循环执行查询与一次性执行查询以获得显着的性能提升?的主要内容,如果未能解决你的问题,请参考以下文章

在不实际执行查询的情况下确定 Oracle 查询执行时间和建议的数据大小

在oracle中怎么将查询到的数据插入到另一个表中

break和continue的区别是啥?

SQL 中将游标循环查询的结果插入到临时表中

oracle 执行存储过程 无法中断 但是是循环执行 怎么办

关于优化在大量数据上执行的 Oracle SQL 查询的建议/技巧