Monat: Februar 2017

Lösung: Index Rebuild: Magic or Voodoo?

Meine Leser haben das Problem natürlich richtig erkannt. Ich danke Jure Bratina, Andrew Sayer und Martin Berger für Ihre Beiträge.
Im folgenden sehen Sie jetzt den ganzen Testcase in kommentieer Form. Das meiste ist, denke ich, selbsterklärend.
Am Anfang wird das Szenario aufgebaut. Das Schema ist, wie gesagt, das SH Beispielschema.

alter table sales add  (sparse varchar2(300)); 
update sales set sparse = rpad('sometext',300, '*');
commit;
create index sparse_idx on sales (sparse);
select blocks from user_segments where segment_name ='SPARSE_IDX';

Lassen Sie uns jetzt die Grösse des Indexsegements prüfen:

select blocks from user_segments where segment_name ='SPARSE_IDX';

   BLOCKS
---------
    44032

select leaf_blocks from user_indexes where index_name ='SPARSE_IDX';

LEAF_BLOCKS
-----------
      41766

Jetzt kommt ein Update, den ich in ähnlicher Form auch in der Original Datenbank gefunden habe:

update sales set sparse=NULL;

918843 Zeilen aktualisiert.

exec dbms_stats.gather_table_stats(user,'SALES');

Und wie wirkt sich das auf die Statistiken und die Segemente aus?

select leaf_blocks from user_indexes where index_name ='SPARSE_IDX';

LEAF_BLOCKS
-----------
          0
select blocks from user_segments where segment_name ='SPARSE_IDX';

    BLOCKS
----------
     44032

Da der Optimizer lediglich die Index Statistiken prüft, nicht aber die Segementstatistiken, hält der Optimizer den Index für winzig klein.
Das also alle nicht null Werte der Spalte sparse im Index sein müssen, ist es aus Sicht des Optimizers am besten, den angeblich kleinen Index zu scanen.
Das Indexsegment hat aber immer noch die volle Grösse. Erst ein Index rebuld schafft hier Abhilfe.

Advertisements

Index Rebuild: Magic or Voodoo?

Den heutigen Blog schreibe ich nicht gerne. Aber ich fühle mich der Wahrheit verpflichtet und das Thema ist zu interessant um es zu verschweigen.

Als in den Freelists gefragt wurde, ob der Index rebuild auch manchmal nützlich sein kann, habe ich das verneint, unter Hinweis auf entsprechende Einträge bei Mr. Index, Richard Foote.

Ich wusste schon, dass ich mich auf dünnen Eis bewege, aber ich  konnte der Chance oberschlau zu sein und einer gängigen Meinung zu widersprechen, einfach nicht widerstehen. Natürlich trat das unvermeidliche ein und Jonathan Lewis korrigierte mich mit den Hinweis, dass ein Index rebuild in manchgen Grenzfällen eben doch nützlich sein kann. Wie hatte ich bloss glauben können, unbemerkt von Jonathan’s Radar durch zu schlüpfen.

Kurz darauf, als wolle das Schicksal mich auch noch mahnen, fiehl mir bei einem Kunden eine Abfrage auf, die offensichtlich ineffizient war. Ich habe die Abfrage auf das SH  schema umgeschrieben und einen kleinen Testcase erzeugt. Wie ich diesen Testcase gemacht habe, werden Sie in der Lösung sehen. Genau das sollen Sie ja erraten.

select time_id from sales where sparse is not null;

Der Exection Plan mit Runtime Statitiken sieht aus wie folgt:


-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                  | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                           |            |      1 |        |      0 |00:00:00.04 |   41770 |
|   1 |  TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| SALES      |      1 |      1 |      0 |00:00:00.04 |   41770 |
|*  2 |   INDEX FULL SCAN                          | SPARSE_IDX |      1 |      1 |      0 |00:00:00.04 |   41770 |
-------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("SPARSE" IS NOT NULL)

Aus welchem Grund wählt der Optimizer einen Full Index Scan? Eine kurze Überprüfung zeigt, dass Full Table scan sehr viel effizienter ist.Zudem ist die Schärtzung (E-Rows) auch noch richtig. Die Statitiken sind also aktuell.

Was ist hier geschehen? Hinweis: Ich habe nach dem DML auf der Tabelle gesucht und ich fand ein update Statement.