【问题标题】:Holistic SQL queries (inside Oracle PLSQL) and UX整体 SQL 查询(在 Oracle PLSQL 内)和 UX
【发布时间】:2026-02-05 19:55:02
【问题描述】:

我有一个关于如何处理整体 SQL 查询错误的问题。我们正在使用 Oracle PL/SQL。我们的大部分代码库都是逐行处理,最终导致性能极差。据我了解,最大的问题是 PL/SQL 和 SQL 引擎之间的上下文切换。

问题在于用户不知道出了什么问题。旧样式就像:

  • 部分数据上方的光标
  • 如果数据存在,则在另一个表中触发 SELECT(计数),如果不存在则显示 errormsg
  • 选择该数据
  • 如果数据存在,则在另一个表中触发第二个 SELECT(计数),如果不存在则显示 errormsg
  • 选择该数据
  • 修改其他一些表

这可能会持续 10-20 张桌子。它基本上很像一个 C 程序。可以将其改造成类似:

UPDATE (
  SELECT TAB1.Status,
         10 AS New_Status
  FROM   TAB1
  INNER  JOIN TAB2 ON TAB1.FieldX = TAB2.FieldX
  INNER  ..
  INNER  ..
  INNER  ..
  INNER  ..
  LEFT   ..
  LEFT   ..
  WHERE  TAB1.FieldY = 2
  AND    TAB3.FieldA = 'ABC'
  AND    ..
  AND    ..
  AND    ..
  AND    ..
) TAB
SET   TAB.Status = New_Status
WHERE TAB.Status = 5;

像这样的整体 SELECT 会极大地加速很多事情。我更改了一些类似的查询,这些查询从 5 小时缩短到 3 分钟,但这有点容易,因为它是一项无需人工交互的服务。

问题是,如果有人填写表格并等待回复,您将如何处理此类事情。因此,如果出现问题,他们需要一个 errormsg。我想到的唯一解决方案是检查行是否已更新,如果没有则跳转到仍然执行所有单个选择以确定该错误的另一个代码部分。但是在每次更改之后,我们都必须更新整体选择和所有单项选择。猜测一段时间后它们会有所不同并导致更多问题。

另一种解决方案是通用 errormsg,它会导致每天调用数百次,我们将 50 个变量替换到查询中,杀死一些 where 条件/连接以找出过滤掉所需行的条件。

那么,什么是正确的方法来获得性能并且仍然有点用户友好。目前我们的系统感觉无法使用缓慢。如果您按下一个按钮,您通常需要等待很长时间(通常为 3-10 秒,一些更复杂的任务需要 5 分钟)。

【问题讨论】:

  • 所以,简而言之,您是说应用程序根据用户输入运行一些复杂的更新语句,可能会更新 0 行,在这种情况下,您需要返回一个向用户显示错误并指出问题出在他们提供的数据中?如果允许用户输入不存在的信息,听起来您的应用程序中可能存在某种验证问题。表之间是否存在外键?应用端的信息是如何缓存的?我们在谈论什么样的数据和应用程序?
  • 我们谈论的是仓库管理系统。让我们想象一下,用户想要将一个托盘放入他刚刚扫描了条形码的存储箱中。我们需要检查该储物箱是否被锁定,该类型的储物箱是否允许该托盘类型,该储物箱是否只允许某些物品,该储物箱可容纳多少个托盘等等。所以有需要检查大量实时数据,因为许多其他人都在使用相同的数据,所以状态很重要。

标签: oracle performance plsql user-experience


【解决方案1】:

对于大量数据,基于集合的操作比基于行的操作更快。但是基于集合的操作主要适用于批处理任务。 UI 任务通常以逐行方式处理少量数据。

因此,您的真正目标似乎应该是了解为什么您的个人陈述需要这么长时间。

“如果你按下一个按钮,你通常需要等待很长时间(通常是 3-10 秒,在一些复杂的任务上需要 5 分钟”

这显然是不可接受的。同样清楚的是,我们无法解释它:我们没有访问权限或领域知识来诊断系统性能问题。可能你需要说服你的老板接受几天的现场咨询。

但这里有一个探索途径:锁定。

“许多其他人使用相同的数据,所以状态很重要”

也许您的问题不是由于查询缓慢,而是由于更新等待共享资源的语句?如果是这样,更好的(即悲观的)锁定策略可能会有所帮助。


“这就是为什么我说人们不需要知道更多”

数据结构决定算法。业务领域的特殊性质及其数据存储方式是编写执行代码的关键。为什么搜索中有二十个表?为什么对这些表运行查询需要这么长时间? STORAGE_BIN_ID 不是所有这些表的主键吗?

另外,为什么用户要扫描单个垃圾箱上的条形码,直到找到他们想要的一个?对他们来说,为 bin 指定标准似乎会更有效,然后基于集合的查询可以分配最接近他们位置的匹配项。

或者您可能正在尝试编写一个查询来解决多个用例?

【讨论】:

  • 锁定不是问题。假设有人想在没有指定确切存储箱的情况下创建进入某个区域的交通工具。该游标可能会在 50k 个存储箱上方循环,并检查 20 个不同表中的每个存储箱,直到找到一个有效的存储箱。可能会很快发生,或者在该光标内经过 2000 轮之后,因此在 40000 次快速查询之后。
  • 假设我对您的业务或数据架构一无所知。这是我的主要观点。我不知道。 SO上的其他人也不知道。这是一个超出 SO 能力范围的问题。
  • 没有人需要知道更多。问题应该很清楚了。如果我批量处理大量数据,它会很快,但我不知道如何告诉用户出了什么问题。如果我逐行处理数据,它会非常慢,但我知道确切的问题并且可以显示它。人们不需要其他信息,除非他们怀疑其他地方的问题。只是需要检查许多有状态数据的变量,没有办法绕过它。所以问题是是否有比逐行或批处理结合逐行(仅针对错误)更好的方法。
  • @aLpenbog 你只认为没有人需要知道更多,因为你(大概)知道你的数据库和应用程序。我们没有。 APC 建议(我同意)答案可能并不像您想象的那么简单。首先,如果您正在寻找第一个可用的存储箱,为什么不编写一个查询所有相关表的查询,如果它没有找到一个箱,那么就没有可用的箱。这不是挖掘单个查询以找出为什么没有可用的垃圾箱的情况,是吗?您要么有可用的垃圾箱,要么没有。
  • 是的,客户会打电话给我们并告诉我们有很多免费的垃圾箱,我们必须看看有什么问题告诉他他的产品不允许混合其他产品,或者仅剩下的箱子更重等等,这只是数千种不同交互的一个例子。这就是为什么我说人们不需要知道更多我的问题仍然是逐行缓慢但我知道为什么行被过滤掉并且可以向用户输出一些东西而我不能通过快速批处理来做到这一点。