Sql 确保Oracle查询中顺序一致的最佳方法是什么?

Sql 确保Oracle查询中顺序一致的最佳方法是什么?,sql,oracle,sorting,sql-order-by,data-consistency,Sql,Oracle,Sorting,Sql Order By,Data Consistency,我有一个程序,需要在许多非常大的Oracle表(最大的表有数千万行)上运行查询。这些查询的输出被输入到另一个进程中,该进程(作为一个副作用)可以记录查询的进度(即,获取的最后一行) 如果任务由于某种原因中途停止,可以重新启动,那就太好了。为此,查询必须以一致的顺序返回行,因此必须对其进行排序。显然,要做的事情是按主键排序;然而,与未排序的解决方案相比,在性能(索引访问)方面,这可能会受到惩罚。鉴于重启可能永远不会发生,这是不可取的 是否有一些技巧可以确保以另一种方式进行一致的排序?在这种情况下,

我有一个程序,需要在许多非常大的Oracle表(最大的表有数千万行)上运行查询。这些查询的输出被输入到另一个进程中,该进程(作为一个副作用)可以记录查询的进度(即,获取的最后一行)

如果任务由于某种原因中途停止,可以重新启动,那就太好了。为此,查询必须以一致的顺序返回行,因此必须对其进行排序。显然,要做的事情是按主键排序;然而,与未排序的解决方案相比,在性能(索引访问)方面,这可能会受到惩罚。鉴于重启可能永远不会发生,这是不可取的

是否有一些技巧可以确保以另一种方式进行一致的排序?在这种情况下,还有其他关于保持性能的建议吗

编辑:我一直在环顾四周,看到有人提到“rowid订购”。这是有用的还是可能的

编辑2:我正在添加一些基准:

  • 在没有命令的情况下:17秒
  • 按主键排序:46秒
  • 按rowid排序:43秒

因此,任何orderby都会对性能产生严重影响,而使用rowid几乎没有什么区别。公认的答案是-没有简单的方法可以做到这一点。

我能想到的最好的建议是减少可能停止进程的问题发生的机会,这意味着保持代码的简单。没有游标,没有提交,没有尝试移动部分数据,只有直接的SQL语句


除非完全重新启动是一个完全不可接受的灾难,否则我会追求简单,而不需要任何部分重新启动代码。

我能想到的最好建议是减少可能停止进程的问题发生的机会,这意味着保持代码简单。没有游标,没有提交,没有尝试移动部分数据,只有直接的SQL语句


除非完全重新启动是一个完全不可接受的灾难,否则我会追求简单,根本不需要任何部分重新启动代码。

如果您想要一些顺序,并且查询的数据未排序,那么您仍然需要对其进行排序,并花费一些资源进行排序。
因此,优化至少有两种变体:

  • 最大限度地减少在分类上花费的资源
  • 查询已排序的数据
  • 对于第一个变量,Oracle自行计算最佳变量,以最小化数据访问和总体查询时间。可以选择优化器已经使用的唯一索引中涉及的排序顺序,但这是一种非常有问题的策略

    第二个变体是关于索引组织的表,以及关于强制Oracle使用某些特定索引的提示。若您需要处理某个特定表中几乎所有的记录,那个么这似乎是可以的,但若查询的选择性很高,那个么即使是在单个表上,它也会显著减慢进程

    考虑一个具有代理主键的表,它保存有10年事务历史的数据。如果您只需要上一年的数据,并且您强制按主键订购,则Oracle需要逐个处理所有10年的记录,以查找属于某一年的所有记录。
    但如果您需要此表中9年的数据,则全表扫描可能比基于索引的选择更快。
    所以,查询的选择性是在完整表扫描和结果排序之间进行选择的关键

    为了存储结果并重新启动查询,一个好的解决方案是使用Oracle为另一个进程提供数据。
    队列中所有未处理的消息都重定向到异常队列,可以在该队列中单独处理。
    因为您没有为所选消息指定确切的顺序,所以我认为您只需要对未处理的部分记录进行排序。如果这是真的,那么使用AQ,您根本不需要订购,甚至可以并行处理记录


    因此,最后,从我的观点来看,这才是您真正需要的。

    如果您需要某种顺序,并且查询的数据未排序,那么您仍然需要对其进行排序,并花费一些资源进行排序。
    因此,优化至少有两种变体:

  • 最大限度地减少在分类上花费的资源
  • 查询已排序的数据
  • 对于第一个变量,Oracle自行计算最佳变量,以最小化数据访问和总体查询时间。可以选择优化器已经使用的唯一索引中涉及的排序顺序,但这是一种非常有问题的策略

    第二个变体是关于索引组织的表,以及关于强制Oracle使用某些特定索引的提示。若您需要处理某个特定表中几乎所有的记录,那个么这似乎是可以的,但若查询的选择性很高,那个么即使是在单个表上,它也会显著减慢进程

    考虑一个具有代理主键的表,它保存有10年事务历史的数据。如果您只需要上一年的数据,并且您强制按主键订购,则Oracle需要逐个处理所有10年的记录,以查找属于某一年的所有记录。
    但如果您需要此表中9年的数据,则全表扫描可能比基于索引的选择更快。
    所以,查询的选择性是在完整表扫描和结果排序之间进行选择的关键

    为了存储结果并重新启动查询,一个好的解决方案是使用Oracle为另一个进程提供数据。
    队列中所有未处理的消息都重定向到异常队列,可以在该队列中单独处理。
    因为您没有为所选消息指定确切的顺序,所以我认为您只需要对未处理的部分记录进行排序。如果这是真的,那么使用AQ,您根本不需要订购,甚至可以并行处理记录


    因此,最后,从我的观点来看,这才是您真正需要的。

    您可以跳过排序,只需使用类似于
    SET is\u processed='Y'的内容更新您处理的记录