sql >> Database >  >> RDS >> Oracle

Waarom voegt Oracle hier een verborgen kolom toe?

In Oracle release 11g heeft Oracle een nieuwe optimalisatietechniek geïntroduceerd om de prestaties van DDL-bewerkingen te verbeteren. Deze nieuwe functie zorgt voor een extreem snelle uitvoeringstijd bij het toevoegen van een NIET NULL kolom met standaardwaarde naar een bestaande tabel. Sinds release 12c is de DDL-optimalisatie uitgebreid met NULL kolommen met standaardwaarde.

Overweeg de volgende testtabel met 1.000.000 rijen:

sql> create table xxy
as select rownum a from dual connect by level <= 1e6
;
sql> select /*+ gather_plan_statistics */ count(1) from xxy;
sql> select * from table(dbms_xplan.display_cursor); 

Nu gaan we een extra niet-null-kolom toevoegen met een standaardwaarde in verschillende sessies voor 11g en 12c:

11g> alter table xxy add b number default 1;
     --Table XXY altered. Elapsed: 00:01:00.998

12c> alter table xxy add b number default 1;
     --Table XXY altered. Elapsed: 00:00:00.052

Let op het verschil in de uitvoeringstijd:1M rijen bijgewerkt in 5 ms!?

Uitvoeringsplan toont:

11g> select count(1) from xxy where b = 1;
  COUNT(1)
----------
   1000000
11g> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |  1040 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |    13 |            |          |
|*  2 |   TABLE ACCESS FULL| XXY  |   898K|    11M|  1040   (1)| 00:00:13 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("B"=1)
Note
-----
   - dynamic sampling used for this statement (level=2)

12c> select count(1) from xxy where b = 1;
12c> select * from table(dbms_xplan.display_cursor);
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |   429 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |     5 |            |          |
|*  2 |   TABLE ACCESS FULL| XXY  |  1000K|  4882K|   429   (2)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00002$",0)),NULL,NVL("
              B",1),'0',NVL("B",1),'1',"B")=1)
Note
-----
   - statistics feedback used for this statement

Het uitvoeringsplan op 12c toont in tegenstelling tot 11g een complex predikaatgedeelte met een nieuwe interne kolom SYS_NC00006$ .

Dit predikaat geeft aan dat Oracle intern nog steeds overweegt dat de B-kolom mogelijk niet-standaardwaarden kan bevatten. Het betekent - Oracle werkt in eerste instantie niet elke rij fysiek bij met de standaardwaarde.

Waarom een ​​nieuwe interne kolom SYS_NC00006$ is gecreëerd?

12c> select column_name, virtual_column, hidden_column, user_generated 
from user_tab_cols
where table_name = 'XXY'
;
COLUMN_NAME      VIR HID USE
---------------- --- --- ---
B                NO  NO  YES
SYS_NC00002$     NO  YES NO 
A                NO  NO  YES

12c> select a, b, SYS_NC00002$ hid from xxy where a in (1,10);

        A          B HID            
---------- ---------- ----------------
         1          1                 
        10          1                 

12c> update xxy set b=1 where a=10 and b=1;
1 row updated.

12c> select a, b, SYS_NC00002$ hid from xxy where a in (1,10);
         A          B HID            
---------- ---------- ----------------
         1          1                 
        10          1 01              

Let op het verschil in de waarden van B en gerelateerde interne kolommen. Oracle controleert eenvoudig de door het systeem gegenereerde interne kolom (bijv. SYS_NC00006$ ) en via de SYS_OP_VECBIT functie of de standaardwaarde van de B-kolom of de echte waarde die is gewijzigd via een expliciete DML-instructie moet worden overwogen.

Wat is er met twee aparte alter-statements?

12c> alter table xxy add (b integer);
12c> alter table xxy modify b default 1;

12c> select count(b), count(coalesce(b,0)) nulls  from xxy where b = 1 or b is null;

  COUNT(B)      NULLS
---------- ----------
         0    1000000

De waarde van de nieuwe kolom blijft NULL voor alle rijen. Er zijn geen echte updates nodig, daarom wordt het DDL-statement niet geoptimaliseerd.

Hier is een OTN-artikel waarin de nieuwe DDL-optimalisatie in meer detail wordt uitgelegd.




  1. Wat gebeurt er met de primaire sleutel-ID als deze de limiet overschrijdt?

  2. Hoe vind je vergelijkbare resultaten en sorteer je op overeenkomst?

  3. Installeer en maak verbinding met PostgreSQL 10 op Ubuntu 16.04

  4. Wijzig het MySQL-stuurprogramma dat door Joomla wordt gebruikt