Hidden features in Oracle

2019-01-12 19:37发布

I enjoyed the answers and questions about hidden features in sql server

What can you tell us about Oracle?
Hidden tables, inner workings of ..., secret stored procs, package that has good utils...

21条回答
神经病院院长
2楼-- · 2019-01-12 20:03

"Full table scans are not always bad. Indexes are not always good."

An index-based access method is less efficient at reading rows than a full scan when you measure it in terms of rows accessed per unit of work (typically per logical read). However many tools will interpret a full table scan as a sign of inefficiency.

Take an example where you are reading a few hundred invoices frmo an invoice table and looking up a payment method in a small lookup table. Using an index to probe the lookup table for every invoice probably means three or four logical io's per invoice. However, a full scan of the lookup table in preparation for a hash join from the invoice data would probably require only a couple of logical reads, and the hash join itself would cmoplete in memory at almost no cost at all.

However many tools would look at this and see "full table scan", and tell you to try to use an index. If you do so then you may have just de-tuned your code.

Incidentally over reliance on indexes, as in the above example, causes the "Buffer Cache Hit Ratio" to rise. This is why the BCHR is mostly nonsense as a predictor of system efficiency.

查看更多
放荡不羁爱自由
3楼-- · 2019-01-12 20:03

The cardinality hint is mostly undocumented.

 explain plan for
 select /*+ cardinality(@inner 5000) */ *
 from   (select /*+ qb_name(inner) */ * from dual)
 /
 select * from table(dbms_xplan.display)
 /
 --------------------------------------------------------------------------
 | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
 --------------------------------------------------------------------------
 |   0 | SELECT STATEMENT  |      |  5000 | 10000 |     2   (0)| 00:00:01 |
 |   1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
 --------------------------------------------------------------------------
查看更多
该账号已被封号
4楼-- · 2019-01-12 20:03

I don't know if this counts as hidden, but I was pretty happy when I saw this way of quickly seeing what happened with a SQL statement you are tuning.

SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM DUAL;

SELECT * FROM TABLE(dbms_xplan.display_cursor( NULL, NULL, 'RUNSTATS_LAST'))
;

PLAN_TABLE_OUTPUT
-----------------------------------------------------
SQL_ID  5z36y0tq909a8, child number 0
-------------------------------------
SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM DUAL

Plan hash value: 272002086

---------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
---------------------------------------------------------------------------------------------
|   1 |  TABLE ACCESS FULL| DUAL |      1 |      1 |      1 |00:00:00.02 |       3 |      2 |
---------------------------------------------------------------------------------------------


12 rows selected.

Where:

  • E-Rows is estimated rows.
  • A-Rows is actual rows.
  • A-Time is actual time.
  • Buffers is actual buffers.

Where the estimated plan varies from the actual execution by orders of magnitude, you know you have problems.

查看更多
走好不送
5楼-- · 2019-01-12 20:03
Bombasti
6楼-- · 2019-01-12 20:05

Since Apex is now part of every Oracle database, these Apex utility functions are useful even if you aren't using Apex:

SQL> declare
  2    v_array apex_application_global.vc_arr2;
  3    v_string varchar2(2000);
  4  begin
  5  
  6    -- Convert delimited string to array
  7    v_array := apex_util.string_to_table('alpha,beta,gamma,delta', ',');
  8    for i in 1..v_array.count
  9    loop
 10      dbms_output.put_line(v_array(i));
 11    end loop;
 12  
 13    -- Convert array to delimited string
 14    v_string := apex_util.table_to_string(v_array,'|');
 15    dbms_output.put_line(v_string);
 16  end;
 17  /
alpha
beta
gamma
delta
alpha|beta|gamma|delta

PL/SQL procedure successfully completed.
查看更多
Lonely孤独者°
7楼-- · 2019-01-12 20:05

Scalar subquery caching is one of the most surprising features in Oracle

-- my_function is NOT deterministic but it is cached!
select t.x, t.y, (select my_function(t.x) from dual)
from t

-- logically equivalent to this, uncached
select t.x, t.y, my_function(t.x) from t

The "caching" subquery above evaluates my_function(t.x) only once per unique value of t.x. If you have large partitions of the same t.x value, this will immensely speed up your queries, even if my_function is not declared DETERMINISTIC. Even if it was DETERMINISTIC, you can safe yourself a possibly expensive SQL -> PL/SQL context switch.

Of course, if my_function is not a deterministic function, then this can lead to wrong results, so be careful!

查看更多
登录 后发表回答