我正在寻找在实际使用微积分之前要计算其行数的最佳方法。原因是我需要证明“已分析的1/100行”,“已分析的2/100行”等反馈。
我说的是大约7000行,执行计数的时间相差2分钟。
最糟糕的是,现在我必须使用查询来获取计数,然后打开一个与上一个完全相同的游标(计数除外)并开始分析,因此代码是复制,并且每次我需要修改where子句时,我都必须做两次。
我想到将光标放在一个局部变量中,然后在pl / sql while循环中运行以增加一个计数器,但是我不确定性能,所以这就是为什么我要向您提出建议的原因。
真的希望答案不会是使用包含总行数的已打开游标的某些魔术属性,因为我会觉得很愚蠢:(
除非获得可靠的性能提升,否则我宁愿不使用count(*)而不是(partition by),因为我认为一眼难以理解。
感谢所有人
答案 0 :(得分:0)
您可以使用COUNT(*) OVER()
:
DECLARE
CURSOR my_cur IS
SELECT t.c, COUNT(*) OVER() AS total FROM tab t;
v_c INT;
v_total_rows INT;
v_i INT :=0;
BEGIN
OPEN my_cur;
LOOP
EXIT WHEN my_cur%NOTFOUND;
FETCH my_cur INTO v_c, v_total_rows;
IF v_i = 0 THEN
DBMS_OUTPUT.put_line('Total number of rows to process: ' || v_total_rows);
END IF;
DBMS_OUTPUT.PUT_LINE('Current value :' || v_c);
DBMS_OUTPUT.PUT_LINE('Progress: ' || 100.0 * v_i / v_total_rows || '%');
v_i := v_i + 1;
END LOOP;
CLOSE my_cur;
END;
//
您可以使用SET_SESSION_LONGOPS来代替打印到DBMS_OUTPUT
答案 1 :(得分:0)
如果您需要了解表的全部行数,则可以使用数据字典的num_rows
(只要统计信息是最新的):
CREATE TABLE mytest AS SELECT * FROM all_objects;
BEGIN dbms_stats.gather_table_stats(user, 'MYTEST'); END;
/
SELECT num_rows FROM user_tables WHERE table_name='MYTEST';
-- 60715
如果您的查询更复杂并且可以过滤出行或执行其他一些奇特的事情,并且如果对预期的行数的估计足够好,则可以使用Oracle的内置查询计划程序。它需要弄清楚需要多少行才能找到查询它的最佳方法:
EXPLAIN PLAN SET STATEMENT_ID = 'st1-seq' FOR
SELECT * FROM mytest WHERE object_type = 'SEQUENCE';
SELECT cardinality from plan_table WHERE statement_id='st1-seq' and operation='SELECT STATEMENT';
10
EXPLAIN PLAN SET STATEMENT_ID = 'st1-java' FOR
SELECT * FROM mytest WHERE object_type = 'JAVA CLASS';
SELECT cardinality from plan_table WHERE statement_id='st1-java' and operation='SELECT STATEMENT';
37563