获取前 10 个未使用的手册序列号

2023-12-24

我想从某个范围中查找前 10 个未使用的手动序列号。

请在下面找到我的查询:

select X1.* From
    (Select Rownum seq_number From Dual Connect By Rownum <= 
         (Select LPAD(9,(UTC.DATA_PRECISION - UTC.DATA_SCALE),9) 
          From User_Tab_Columns UTC 
          where UTC.Table_Name = 'Table_Name' And UTC.Column_Name = 'seq_number')) X1,
Table_Name X2
Where X1.seq_number = X2.seq_number (+)
  And X2.Rowid is Null
  And Rownum <= 10

尽管它提供了所需的输出,但我担心[如果有的话]造成的负载,因为我们每天将多次使用此查询。

请告知是否有办法优化此查询。

附加信息: 在 Table_Name T2 上,在 (seq_number) 上定义了唯一索引

工作示例:

create table TEMP_TABLE_NAME ( seq_number number(6))

insert into TEMP_TABLE_NAME 
select distinct trunc(dbms_random.VALUE(1,5000)) seq_number 
from dual
connect by rownum <= 1000


create unique index TEMP_TABLE_NAME_IDX on TEMP_TABLE_NAME(seq_Number)


SELECT T1.*
  FROM (    SELECT ROWNUM seq_number
              FROM DUAL
        CONNECT BY ROWNUM <=
                      (SELECT LPAD (9,(UTC.DATA_PRECISION - UTC.DATA_SCALE),9)
                         FROM User_Tab_Columns UTC
                        WHERE     UTC.Table_Name = 'TEMP_TABLE_NAME'
                              AND UTC.Column_Name = 'SEQ_NUMBER')) T1,
       TEMP_TABLE_NAME T2
 WHERE     T1.seq_number = T2.seq_number(+)
       AND T2.ROWID IS NULL
       AND ROWNUM <= 10

对我来说,我的查询给出了以下输出。表中随机创建的数字包括 7 和 8,因此它们被忽略。重点是获取前 10 个未使用的数字。

1
2
3
4
5
6
9
10
11
12

First我将替换这个复杂的子查询:

Select Rownum seq_number From Dual Connect By Rownum <= 
         (Select LPAD(9,(UTC.DATA_PRECISION - UTC.DATA_SCALE),9) 
          From User_Tab_Columns UTC 
          where UTC.Table_Name = 'Table_Name' And UTC.Column_Name = 'seq_number')

与这个:

Select Rownum As seq_number From Dual 
Connect By Rownum <= (Select max( seq_number ) + 10 From TEMP_TABLE_NAME ) 

甚至用一个简单的常数:

Select Rownum As seq_number From Dual Connect By Rownum <= 1000000

坦率地说,您的子查询不适用于非常基本的情况:

create table TEMP_TABLE_NAME(
  seq_number NUMBER
);

SELECT LPAD (9,(UTC.DATA_PRECISION - UTC.DATA_SCALE),9) as x , 
       UTC.DATA_PRECISION, UTC.DATA_SCALE, UTC.COLUMN_NAME
FROM User_Tab_Columns UTC
WHERE     UTC.Table_Name = 'TEMP_TABLE_NAME'
  AND UTC.Column_Name = 'SEQ_NUMBER'
;

X        DATA_PRECISION DATA_SCALE COLUMN_NAME
-------- -------------- ---------- -----------
  (null)         (null)     (null) SEQ_NUMBER

还有第二种情况:

create table TEMP_TABLE_NAME(
  seq_number NUMBER(15,0)
);

在这种情况下,子查询尝试生成 999999999999999 行,这很快就会导致内存不足错误

SELECT count(*) FROM (
 SELECT ROWNUM seq_number
              FROM DUAL
        CONNECT BY ROWNUM <=
                      (SELECT LPAD (9,(UTC.DATA_PRECISION - UTC.DATA_SCALE),9)
                         FROM User_Tab_Columns UTC
                        WHERE     UTC.Table_Name = 'TEMP_TABLE_NAME'
                              AND UTC.Column_Name = 'SEQ_NUMBER')
);

ORA-30009: Not enough memory for CONNECT BY operation
30009. 0000 -  "Not enough memory for %s operation"
*Cause:    The memory size was not sufficient to process all the levels of the
           hierarchy specified by the query.
*Action:   In WORKAREA_SIZE_POLICY=AUTO mode, set PGA_AGGREGATE_TARGET to
           a reasonably larger value.
           Or, in WORKAREA_SIZE_POLICY=MANUAL mode, set SORT_AREA_SIZE to a
           reasonably larger value.

其次,您的查询不是确定性的!
它强烈依赖于物理表结构,并且不使用强加正确的顺序ORDER BY clause.
记住->维基百科 - 排序依据 https://en.wikipedia.org/wiki/Order_by

ORDER BY是对结果集中的行进行排序的唯一方法。没有 该子句中,关系数据库系统可以返回任意行中的行 命令。如果需要订购,则必须提供 ORDER BY 应用程序发送的 SELECT 语句。

考虑这个测试用例:

create table TEMP_TABLE_NAME 
as SELECT * FROM (
    select rownum as seq_number , t.*
    from ALL_OBJECTS t
    cross join ( select * from dual connect by level <= 10)
    where rownum <= 100000
)
ORDER BY DBMS_RANDOM.Value;
create unique index TEMP_TABLE_NAME_IDX on TEMP_TABLE_NAME(seq_Number);

select count(*) from TEMP_TABLE_NAME;
  COUNT(*)
----------
    100000

DELETE FROM TEMP_TABLE_NAME
WHERE seq_number between 10000 and 10002
  OR seq_number between 20000 and 20002
  OR seq_number between 30000 and 30002
  OR seq_number between 40000 and 40002
  OR seq_number between 50000 and 50002
  OR seq_number between 60000 and 60002
  ;

如果索引存在,那么结果就OK:

SELECT T1.*
  FROM (    SELECT ROWNUM seq_number
              FROM DUAL
        CONNECT BY ROWNUM <= 1000000
) T1,
       TEMP_TABLE_NAME T2
 WHERE     T1.seq_number = T2.seq_number(+)
       AND T2.ROWID IS NULL
       AND ROWNUM <= 10
;

SEQ_NUMBER
----------
     10000
     10001
     10002
     20000
     20001
     20002
     30000
     30001
     30002
     40000

但是,当有一天有人删除索引,或者优化器由于某种原因决定不使用该索引时,会发生什么情况?
根据定义:如果没有 ORDER BY,关系数据库系统可能会以任何顺序返回行。我使用提示模拟这些情况:

SELECT /*+ NO_INDEX(T2) */ T1.*
  FROM (    SELECT ROWNUM seq_number
              FROM DUAL
        CONNECT BY ROWNUM <= 1000000
) T1,
       TEMP_TABLE_NAME T2
 WHERE     T1.seq_number = T2.seq_number(+)
       AND T2.ROWID IS NULL
       AND ROWNUM <= 10
;

SEQ_NUMBER
----------
    213856
    910281
    668862
    412743
    295487
    214762
    788486
    346216
    777734
    806457

下面的查询强制使用正确的顺序ORDER BY子句并给出可重现的结果,无论是否存在正确的索引。
我正在使用推荐的 ANSI SQL LEFT JOIN 子句,而不是过时的WHERE .... (+) syntax.

SELECT  * FROM (
    SELECT /*+ NO_INDEX(T2) */ T1.*
      FROM (    SELECT ROWNUM seq_number
                  FROM DUAL
            CONNECT BY ROWNUM <= 1000000
    ) T1 
    LEFT JOIN TEMP_TABLE_NAME T2
    ON T1.seq_number = T2.seq_number
    WHERE T2.ROWID IS NULL
    ORDER BY T1.seq_number
)
WHERE ROWNUM <= 10

表现
检查性能的最简单方法是进行测试 - 运行查询 10-100 次并测量时间:

SET TIMING ON;
DECLARE
   x NUMBER;
BEGIN
   FOR i IN 1..10 LOOP
      SELECT sum( seq_number ) INTO x
      FROM (
           SELECT  * FROM (
            SELECT T1.*
              FROM (    SELECT ROWNUM seq_number
                          FROM DUAL
                    CONNECT BY ROWNUM <= 1000000
            ) T1 
            LEFT JOIN TEMP_TABLE_NAME T2
            ON T1.seq_number = T2.seq_number
            WHERE T2.ROWID IS NULL
            ORDER BY T1.seq_number
            )
            WHERE ROWNUM <= 10
        );
    END LOOP;
END;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:11.750

10 次 - 11.75 秒,因此一次查询需要 1.2 秒。


下一个版本有限制CONNECT BY使用子查询:

SET TIMING ON;
DECLARE
   x NUMBER;
BEGIN
   FOR i IN 1..10 LOOP
      SELECT sum( seq_number ) INTO x
      FROM (
           SELECT  * FROM (
            SELECT T1.*
              FROM (    SELECT ROWNUM seq_number
                          FROM DUAL
                    CONNECT BY ROWNUM <= (Select max( seq_number ) + 10 From TEMP_TABLE_NAME ) 
            ) T1 
            LEFT JOIN TEMP_TABLE_NAME T2
            ON T1.seq_number = T2.seq_number
            WHERE T2.ROWID IS NULL
            ORDER BY T1.seq_number
            )
            WHERE ROWNUM <= 10
        );
    END LOOP;
END;
/
PL/SQL procedure successfully completed.

Elapsed: 00:00:00.986

好多了 - 只需 100 毫秒。
由此得出的结论是,CONNECT BY部分是成本最高的。


另一种尝试是使用预先生成的数字序列高达 1 mln(某种物化视图)的表来代替CONNECT BY每次在内存中动态生成数字的子查询:

create table seq(
   seq_number int primary key
)
ORGANIZATION INDEX ;

INSERT INTO seq 
SELECT level FROM dual
CONNECT BY LEVEL <= 1000000;

SET TIMING ON;
DECLARE
   x NUMBER;
BEGIN
   FOR i IN 1..10 LOOP
      SELECT sum( seq_number ) INTO x
      FROM (
           SELECT  * FROM (
            SELECT T1.*
            FROM seq T1 
            LEFT JOIN TEMP_TABLE_NAME T2
            ON T1.seq_number = T2.seq_number
            WHERE T2.ROWID IS NULL
            ORDER BY T1.seq_number
            )
            WHERE ROWNUM <= 10
        );
    END LOOP;
END;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.398

这是最快的 - 仅 40 毫秒

第一个 1200 毫秒,最后一个 40 毫秒 - 快了 30 倍 (3000 %)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获取前 10 个未使用的手册序列号 的相关文章

  • 我不确定在 SQL 中声明这些变量时出了什么问题

    我有以下代码 USE pricingdb go CREATE TABLE dbo Events 060107 2012 Date Time varchar 20 COLLATE SQL Latin1 General CP1 CI AS NU
  • 如何找到 Oracle 数据库的 URL?

    如何找到 Oracle 数据库的 URL 和端口 Example jdbc oracle thin host port dbName 用户名 密码 是否有我可以查看的 SQL 命令或日志 配置文件 对于甲骨文来说 有一个tnsnames o
  • 从多个表中选择 - 一对多关系

    我有这样的表 表产品 身份证 姓名 表格图像 产品 ID 网址 订单号 表价 产品 ID 组合 货币 价格 表数量 产品 ID 组合 数量 表 Product 与其他表是一对多关系 我需要查询表并得到类似这样的结果 伪数组 ProductI
  • SQL:比较不同表中的两个计数

    我有 3 张桌子 一张桌子上有世界上每个国家及其代币 NAME CODE Afghanistan AFG Albania AL Algeria DZ American Samoa AMSA Andorra AND Angola ANG An
  • 为什么 sql 字段名称中不应该包含逗号?

    人们一直告诉我列名中不应包含空格 我只是想知道 这是为什么 这是我为学校创建的一些数据库表遇到的问题 字段名称包括 Preble 和 Darke 相反 它们需要是 普雷布尔县 俄亥俄州 和 达克县 俄亥俄州 如果它们是行名称 我只需创建一个
  • MySQL中是否有类似Oracle中“level”的函数[重复]

    这个问题在这里已经有答案了 我面临一个场景 如果输入是 10 我想要一个数字序列 1 2 3 10 在甲骨文中levelfunction 提供了该功能 我想知道如何在 MySQL 中执行相同的任务 谢谢 您可以在 mysql 中使用此查询
  • Oracle:如何查找模式中上次更新(任何表)的时间戳?

    有一个Oracle数据库模式 数据很小 但仍然有10 15个表左右 它包含一种配置 路由表 有一个应用程序必须不时轮询此架构 不得使用通知 如果架构中没有数据更新 应用程序应使用其当前的内存版本 如果任何表有任何更新 应用程序应将所有表重新
  • MySQL:你能指定一个随机限制吗?

    有没有办法在 SQL MySQL 中随机化限制数字 我希望能够做的是在查询中获取随机数量的结果以在插入子查询中使用 而无需任何服务器端脚本 我希望能够作为假设说明运行的查询是 SELECT id FROM users ORDER BY RA
  • 以无法破坏的方式限制表中允许的记录数量

    我们有一个 Web 应用程序 Grails 我们将根据用户数量为其出售许可证 数据库 Oracle 10g 中有一个表保存用户 客户将托管自己的软件和数据库副本 有人可以建议一些策略来限制允许存在于用户表中的记录数量 从而使客户无法合理地破
  • (SQL) 识别字段中字符串格式多次出现的位置

    我需要将叙述字段 自由文本 拆分为多行 目前的格式如下 Case Reference Narrative XXXX XX 123456 Endless Text up to 50k characters 在作为文本的叙述字段中 各个条目 当
  • 获取查询的行号

    我有一个查询将返回一行 当表排序时 有什么方法可以找到我正在查询的行的行索引吗 我试过了rowid但当我期待第 7 行时却得到了 582 Eg CategoryID Name I9GDS720K4 CatA LPQTOR25XR CatB
  • 如何打印Oracle中过程的定义?

    oracle中有没有办法查看过程的结构是什么 我正在尝试记录并运行程序 并希望将实际的程序结构存储在我的日志中 您可以查询ALL SOURCE table SELECT text FROM all source WHERE owner lt
  • SQL 大表中的随机行(使用 where 子句)

    我有一个网站 人们可以在其中对汽车进行投票 向用户展示 4 辆汽车 他 她可以投票选出他们最喜欢的汽车 桌子cars有重要的列 car id int 10 not auto increment so has gaps views int 7
  • 如何将自定义类型数组传递给 Postgres 函数

    我有一个自定义类型 CREATE TYPE mytype as id uuid amount numeric 13 4 我想将它传递给具有以下签名的函数 CREATE FUNCTION myschema myfunction id uuid
  • 使用MySQL计算单个表中借方和贷方的余额

    下面的 MySQL 表包含带有关联金额的借方或贷方 操作 如何选择具有非零 余额 的所有 CLIENT ID 我尝试将表连接到自身以计算所有借方和贷方总额 但有些东西无法正常工作 CLIENT ID ACTION TYPE ACTION A
  • 在 Postgres 中的数组字段上应用聚合函数?

    是否可以对整数 字段 或其他数字数组 中的所有值应用聚合 如 avg stddev CREATE TABLE widget measurement integer insert into widget measurement values
  • 更新plpgsql中触发器函数中的多列

    给出以下架构 create table account type a id SERIAL UNIQUE PRIMARY KEY some column VARCHAR create table account type b id SERIA
  • 将多行合并为一行并根据行数附加列

    我正在尝试将同一个表的多行合并为一个 我有一个像这样的示例表 Col1 Col2 Col3 Col4 Col5 Col6 1 BH1 CB 12 CC CC Conveyor Mal 1 BH1 CB 104 ZC ZC Full Emp
  • SQL Group BY,每个组的前 N ​​个项目

    我有一个 SQL 查询 可以获取给定商店中销量最高的 5 件商品 SELECT TOP 5 S UPCCode SUM TotalDollarSales FROM Sales S WHERE S StoreId 1 GROUP BY S U
  • APEX:从临时表下载 BLOB

    我正在尝试使用 Oracle APEX 4 1 1 构建一个简单的查看应用程序 要显示的信息位于与包含 APEX 应用程序访问的架构的数据库不同的数据库上的表中 使用视图 View 访问此远程表 远程表视图 和数据库链接 视图按预期工作 包

随机推荐

  • 如何在页面加载时动态更改aspx页面的标题

    我有一组 ASPX 页面 其中每个页面都有不同的标题 但我想为没有标题的页面设置默认标题 默认标题必须是可配置的 如果这是经典的 ASP NET 不是 MVC 并且您正在使用MasterPage然后你可以设置默认标题Page Load事件在
  • PHP sqlsrv 查询数据库

    我从 MySQL 迁移到 MS SQL Server 并尝试从例程表中获取所有数据 我已连接 但不确定如何使用 sqlsrv 获取数据 这就是我已经走了多远 conn array array UID gt sa PWD gt root Da
  • 在选中列表框中创建选中项目的字符串数组

    如何使用 foreach 循环 或任何其他方式 创建一个包含 checklistbox 中选中项目的数组 我无法知道列表中的项目数量 假设您使用 3 5 或更高版本 object items lb CheckedItems OfType T
  • 凿子3.功能模块Mux4

    我正在按照文档学习 Chisel在 Github 上 https github com ucb bar chisel3 wiki Short 20Users 20Guide 20to 20Chisel 到目前为止 一切都完美无缺 但我还是卡
  • 使用 INSERT 和 AUTO-INCREMENT 列的 SQL 语句中出现错误

    INSERT INTO configuration VALUES News Box Character Count NEWS BOX CHAR COUNT 200 Set the number of characters bytes tha
  • 如何实现制表符补全

    我试图弄清楚如何在 C 应用程序中实现子命令的制表符补全 我希望它的功能与 Git 的制表符补全非常相似 我正在浏览 Git 的源代码 但它并没有引起我的注意 我已经搜索了实现选项卡完成的方法 但没有找到直接的答案 因此我猜测它可能不一定是
  • 如何将hashMap转换为Json文件

    我是偏向Java的 我必须使用 rpc 将 Hashmap 传输到服务器 HashMap Map
  • 在给定 sqlite 进度的情况下,在 Android 中存储图像的规范方法

    我完全清楚 通常不建议将图像作为 blob 存储在数据库中 但我最近遇到this https www sqlite org fasterthanfs html网站记录了 sqlite 在向数据库读取和写入图像 blob 方面的性能提升 简而
  • Android 错误:应用程序意外停止,请重试

    我制作了一个运行良好的应用程序 它显示应用程序已启动的次数 这是代码 import android app Activity import android content SharedPreferences import android o
  • “释放未使用的内核内存”从何而来?

    我经常看到Freeing unused kernel memory xxxK from dmesg 但在 grep rg 的帮助下我永远无法从内核源代码中找到此日志 它从何而来 该行文本不作为单个完整字符串存在 因此您无法对其进行 grep
  • 如何在 Android 的 Volley 中创建一个新的 newRequestQueue

    我有一个片段 我尝试实例化一个新的newRequestQueue使用 Volley API 我尝试像这样实例化它 RequestQueue queue Volley newRequestQueue this 但是 当我尝试创建请求时 出现以
  • 完全删除 Angular4 中的测试

    我使用构建了一个非常小的应用程序angular4 我有一个主应用程序组件 两个子组件和一项服务 我觉得我不需要对这么小的应用程序进行测试 并且想删除与使项目更干净相关的所有测试 所以我的问题是我可以从项目中删除哪些与测试相关的文件 我已经删
  • 选择当前聚焦的元素

    我想在整个文档中找到当前关注的元素 我尝试使用 focusjQuery 1 6 引入的伪类 document find focus But document find focus length总是返回0 您应该能够使用activeEleme
  • 这是矫枉过正,还是对 CakePHP 的 HTML 帮助器的良好利用?

    我刚刚重新格式化了 CakePHP 应用程序的默认布局 我通过将几乎所有内容都放在 html 帮助器方法中来消除尽可能多的内联 html 这很有趣 但我想知道我从这次练习中获得了什么好处 如果有的话
  • 将数组的每个对应元素转换为r中的向量

    我有大量数组 希望将所有这些数组中特定位置的所有元素转换为向量 也就是说 如果我有 2 个数组 如下所示 39 1 2 3 4 5 1 0 00000000 0 00000000 0 0000000 0 000000 0 2 0 06703
  • Ruby Timeout::timeout 不会引发异常,也不会返回记录的内容

    我有这段代码 begin complete results Timeout timeout 4 do results platform search artist album name end rescue Timeout Error pu
  • 如何在Camel路由中使用上下文路径?

    我是骆驼新手 我正在 spring boot 中做一个项目 使用camel作为路由 我注意到 当我去 SwaggerUi 查看 Post 调用的正确功能时 路由的 contextPath 不起作用 public void configure
  • 如何准确测量 C++ 函数使用的时钟周期?

    我知道我必须使用 rdtsc 测量的函数是确定性的 但结果远不能重复 每次运行我得到 5 的振荡 可能的原因有 上下文切换 缓存未命中 您还知道其他原因吗 如何消除它们 TSC 什么rdtsc使用 在多处理器系统上通常不同步 它可能有助于设
  • SparkSQL 超前/滞后函数中的动态/变量偏移

    我们可以以某种方式使用取决于 Spark SQL 中的领先 滞后函数中的列值的偏移值吗 示例 以下是运行良好的方法 val sampleData Seq bob Developer 125000 mark Developer 108000
  • 获取前 10 个未使用的手册序列号

    我想从某个范围中查找前 10 个未使用的手动序列号 请在下面找到我的查询 select X1 From Select Rownum seq number From Dual Connect By Rownum lt Select LPAD