Newsgroup: it.comp.software.database
Titolo: Oracle - Allocazione dello spazio

Salve a tutti esperti di Oracle,
vi illustro il seguente problema:
ho una tabella che ha la seguente struttura:
   A123 (
   OBJECTID         NUMBER (38)   NOT NULL,
   NUM              NUMBER (5)    NOT NULL,
   TIPONUM          VARCHAR2 (2)  NOT NULL,
   DAL              NUMBER (9,3)  NOT NULL,
   AL               NUMBER (9,3)  NOT NULL,
   LEDAL            VARCHAR2 (5)  NOT NULL,
   LEAL             VARCHAR2 (5)  NOT NULL,
   TIPOLOGIA        NUMBER (5)    NOT NULL,
   COORDXCALCOLATA  NUMBER (20,6),
   COORDYCALCOLATA  NUMBER (20,6),
   PERCENTUALE      NUMBER (9,2),
   IDSTRADE         NUMBER (9),
   CODPRO           NUMBER (5)    NOT NULL,
   COORDXEFFETTIVA  NUMBER (20,6),
   COORDYEFFETTIVA  NUMBER (20,6),
   STRINT_          NUMBER (8),
   SDE_STATE_ID     NUMBER (38)   NOT NULL)
tuttora ha la 0 righe ma alloca ben 27Mega con 3330 blocchi.
Qlche ipotesi su tutto questo spazio allocato?
Un saluto a tutti voi.


creata ex-novo oppure già utilizzata?
se già utilizzata ti conviene troncare la tabella droppando lo storage 
se è nuova dipende quanto spazio hai allocato....
Ciao
Matteo

Ciao Matteo,
La tabella è già stata utilizzata.
Essendo parte di una strumento di appoggio per una "replica", posso 
ipotizzare che di dati ne abbia visti e poi, una volta terminata la 
replica, sia stata "svuotata" del contenuto.
Per lo spazio da deallocare, era già mia intenzione di riallocarlo..
Vabbè procederò con una piccola alter ;)
grazie ancora,
Simone

> La tabella è già stata utilizzata.
Puoi provare a fare un delete di tutto anche se è vuota (cosa stupida ma
chissà) e poi prova a fare un analyze della tabella oppure se hai tempo del
database... a me almeno aggiorna l'interfaccia in java col num di record
effettivi magari a te aggiorna le cifre di spazio allocato :oP
Chissà che funzioni...
Poi mi fai sapere?
Ciao spero di esserti stato utile!


Mi spiace intromettermi cosi' ma una delete non puo' azzerare 
l'high-water mark.
Una volta che gli extent sono stati allocati o li riutilizzi oppure usi 
una DDL come la truncate (o la clausula "deallocate unused") per 
rilasciare lo spazio.
Ciao
-- 
Fabrizio Magni
fabrizi...@mycontinent.com
replace mycontinent with europe

Ciao Fabrizio,
ciao aaa,
grazie per i suggerimenti.
Allora, per tutte le tabelle ho fatto l'analyze per ottenere le ultime 
info sulle stesse. Di queste una ventina mi dicono che ad es. il calcolo 
num_row * avg_row_len è pari a 0 , ma dalla dba_segments ho un pò di 
blocchi usati.
Un altro esempio la tabella A128 occupa 19M sulla colonna 
DBA_SEGMENTS.BYTES, mentre il calcolo USER_TABLES.AVG_ROW_LEN * NUM_ROWS 
= 4M.
Questa tabella non rientra in quelle tabelle che occupano spazio da 
deallocare.
Cosa posso verificare per eliminare questa differenza?
In totale lo spazio occupato dalle tabelle per la dba_segments è 570M 
contro i 260M della user_tables.
Problemi di deframmentazione?
A presto,
Simone

 Problemi di deframmentazione?
No, quello e' un altro problema (o meglio: altri problemi).
Scusa se ho mancato di chiarezza o sono stato troppo superficiale (la 
fretta).


 
Ok, ho ricevuto una mail in cui mi si diceva che non ho provato 
l'affermazione cosi' eccomi a ripostare.
Prego di scusare l'uso dell'utente system ma non avevo a disposizione 
altro da qui.
Ho creato un tabella pippo:
SQL> select count(*) from pippo;
   COUNT(*)
----------
      22852
La analizzo e controllo cio' che le statistiche mi dicono:
SQL> exec dbms_stats.gather_table_stats('SYSTEM','PIPPO');
PL/SQL procedure successfully completed.
SQL> select TABLE_NAME,AVG_ROW_LEN,NUM_ROWS from user_tables where 
table_name='PIPPO';
TABLE_NAME                     AVG_ROW_LEN   NUM_ROWS
------------------------------ ----------- ----------
PIPPO                                   63      22852
Nel frattempo ecco cosa la user_segments mi dice dell'allocazione di spazio:
SQL> select BYTES,BLOCKS,EXTENTS from  user_segments where 
SEGMENT_NAME='PIPPO';
      BYTES     BLOCKS    EXTENTS
---------- ---------- ----------
    2097152        256         17
Ora tronco la tabella:
SQL> truncate table pippo;
Table truncated.
SQL> select count(*) from pippo;
   COUNT(*)
----------
          0
Come si vede non contiene righe.
Ma le mie statistiche mi dicono il contrario:
SQL> select TABLE_NAME,AVG_ROW_LEN,NUM_ROWS from user_tables where 
table_name='PIPPO';
TABLE_NAME                     AVG_ROW_LEN   NUM_ROWS
------------------------------ ----------- ----------
PIPPO                                   63      22852
(Ovvio visto che non sono state ricomputate).
Ma la mia user_segments mi da':
SQL> select BYTES,BLOCKS,EXTENTS from  user_segments where 
SEGMENT_NAME='PIPPO';
      BYTES     BLOCKS    EXTENTS
---------- ---------- ----------
      65536          8          1
Cioe' i reali valori di occupazione.
Come si vede un extent e' allocato.
Ogni oggetto ha sempre almeno un extent. Mai meno (anche se non contiene 
nulla).
percio' anche un oggetto vuoto occupa spazio.
Visto che le statistiche non sono sempre calcolate ma a volte solo 
stimate usare quei valori per calcolare l'occupazione di spazio ha poco 
senso (o nulla del tutto).
Spero di aver convinto qualche scettico...
Buona notte.
PS: la tablespace map c'e' anche nella 9i e nella 10gR2 (anche se in 
questa non e' proprio il massimo). Manca invece nella 10gR1.


Ma nessun problema, anzi hai rinfrescato alcune idee disperse nel tempo..
Ho provveduto con una serie di alter table move tablespace a "resettare" 
l'HWM per poi deallocare lo spazio non usato. Così sono riuscito ad 
avere una differenza di spazio di soli 68M tra le due stime.
Il fatto è che i dba del cliente mi stressano facendo i conti dello 
spazio sul num_rows*avg_row_len e non sulla dba_segments.
So abbastanza bene che una tabella può crescere di spazio per vari 
motivi, per mancato studio dello spazio minimo per una insert, al 
chained row, etc. . Mi chiedevo se potevo studiare altro per stimare 
meglio gli oggetti.
Tuttora tramite una alter table move tablespace ho resettato l'hwm e, 
con la dbms_space, ho deallocato lo spazio non usato limitando la 
differenza tra avg*row e segments a 68M. Spero che ai sistemisti possa 
bastare questa poca differenza di stima...
Grazie ancora,
Simone
Ps. ma in oem non esisteva lo strumento per visualizzare la struttura di 
un tablespace? nella 8i si, nella 9i e 10g è sparito?

 
Non per fare polemica con situazioni o DBA che non conosco ma calcolare 
lo spazio nel DB usando num_rows*avg_row_len non ha senso.
Ogni blocco oracle non e' quasi mai pieno cosi' come vi e' spazio libero 
  negli extent (che sono le unita' di allocazione che si devono contare!).
Tra l'altro num_rows e avg_row_len sono statistiche che possono essere 
stimate e non calcolate al centisimo (oltre ad essere ferme nel tempo).
Ripeto: usare quei parametri per conoscere l'occupazione di spazio e' 
follia!!!!
(Consiglia ai DBA la lettura di un manuale).
-- 


 replica, sia stata "svuotata" del contenuto.
Leggendo questa frase mi chiedo perché tu voglia riallocare quella
tabella. Se la tabella ti serve, allora tanto vale lasciarla delle
dimensioni attuali (l'unica preoccupazione che avrei è ricrearla con le
apposite clausole di storage, oppure fare un export/import del db, in
maniera da essere sicuro di avere veramente una allocazione contigua).
Se la tabella non ti serve, allora tanto vale troncarla
Henryx
P.S. tieni presente che senza le opportune opzioni di storage, le
tabelle in oracle tendono a frammentarsi (hai capito bene, si
frammentano)

 frammentano)
Qui intendevi tablespace fragmentation?
Con l'introduzione delle LMT, il problema non sussiste (o comunque la 
sua portata e ridottissima).
O lasci a oracle il compito di decidere la grandezza degli extent (e 
quindi tu hai poche possibilita' di pilotare le scelte) o usi un 
segmento uniforme quindi non avrai *mai* frammentazione delle tablespace.
Discorso diverso se parli di DMT... ma ormai se non per vecchi sistemi o 
bug particolari, queste sono cadute in disuso.
A meno di macroscopici errori la frammentazione delle tablespace e' 
ormai un non-problema.
In tutti i casi e' buona pratica specificare le clausule di storage a 
livello di tablespace e non di oggetto.
(oppure per tabella frammentata intendevi row chaining e migration?)
ciao


 (oppure per tabella frammentata intendevi row chaining e migration?)
Sinceramente non capisco cosa intendi. Per tabella frammentata intendo
una tabella da più di un extent non contiguo
Henryx


Ciao Enrico,
avevo proprio paura che tu scrivessi una cosa simile.
1 extent per oggetto e' ormai un ito oracle (ti cosiglio la lettura di 
Howard J Rogers, Jeremiah Wilton o Jonathan Lewis).
(Prova questo link per farti un'idea generale 
http://www.speakeasy.org/~jwilton/oracle/oracle-misconceptions.html
).
Avere un oggetto in un sole extent non aumentera' le tue performancema 
ti portera' ad avere problemi (come la frammentazione di cui parlavi) e 
maggiore lavoro.
Non e' una caso di paranoia ma di bad practice.
Perfino nelle vecchie DMT si era arrivati a sconsigliare il singolo 
extent per oggetto.
Mentre per le cluasule di storage lo ribadisco: tranne casi 
particolarissimi meglio averle a livello tablespace.
Al massimo creane altre dove hai requisiti particolari.


Vi ringrazio tutti per le informazioni che mi avete fornito.
Grazie ancora per tutto il supporto..
Simone

 maggiore lavoro.
Scusa, ma questo mi sembra qualcosa di differente da quello che ho
provato[1]. Avendo la tabella su più extent (clausola STORAGE impostata
con i valori di default) mi sono ritrovato con la tabella frammentata
all'ennesima potenza (era una tabella di auditing in cui venivano fatti
quattro inserimenti per ogni record presente sulla tabella principale) e
dalle prestazioni più che infime
Henryx
[1] a meno che non stiamo utilizzando lo stesso termine per indicare due
operazioni differenti

 operazioni differenti
Ho paura che stiamo parlando proprio della stessa cosa.
PS: spero di non aver dato il tono sbagliato alla mail.
Sto solo tentando di combattere un mito e una cattiva pratica. Non e' 
qualcosa di personale.


 mi spiace scriverlo ma mi sono perso la dimostrazione.
Non c'è stata nessuna dimostrazione e forse è meglio farla.
In questo momento, sulla mia istanza di Oracle (9.2.0.5), ho creato due
 tabelle (tab1 e tab2) in cui, per tab1, ho queste clausole di storage:
STORAGE (
            INITIAL 128K
            NEXT 128K
            MINEXTENTS 1
            MAXEXTENTS 4096
            PCTINCREASE 0
            FREELISTS 1
            FREELIST GROUPS 1
            BUFFER_POOL DEFAULT
           )
Per tab2, invece, le clausole di storage sono queste:
STORAGE (
            INITIAL 213M
            NEXT 104M
            MINEXTENTS 1
            MAXEXTENTS 4096
            PCTINCREASE 0
            FREELISTS 1
            FREELIST GROUPS 1
            BUFFER_POOL DEFAULT
           )
La tablespace su cui risiedono le tabelle (attualmente occupata per il 70%)
è stata creata con impostazioni simili a queste (sostanzialmente, cambia
solo
il nome della tablespace e dei datafile):
CREATE TABLESPACE PIPPO DATAFILE
  'C:\ORACLE\ORADATA\TEST\PIPPO.DBF' SIZE 2000M AUTOEXTEND OFF,
  'C:\ORACLE\ORADATA\TEST\PIPPO1.DBF' SIZE 16K AUTOEXTEND OFF,
  'C:\ORACLE\ORADATA\TEST\PIPPO2.DBF' SIZE 16K AUTOEXTEND OFF,
  'C:\ORACLE\ORADATA\TEST\PIPPO3.ORA' SIZE 2000M AUTOEXTEND OFF,
  'C:\ORACLE\ORADATA\TEST\PIPPO4.ORA2' SIZE 2000M AUTOEXTEND OFF
MINIMUM EXTENT 64K
NOLOGGING
DEFAULT STORAGE (
                  INITIAL 128K
                  NEXT 128K
                  MINEXTENTS 1
                  MAXEXTENTS 4096
                  PCTINCREASE 0
                )
ONLINE
PERMANENT
EXTENT MANAGEMENT DICTIONARY
BLOCKSIZE 8K;
Le tabelle sono identiche sia come struttura di colonne, sia come dati
inseriti (2868115 record per 11 colonne). Le tabelle non hanno indici,
chiavi
primarie o constraints.
La colonna EXTENTS di USER_SEGMENTS riporta, per tab1, il valore 1667,
mentre per tab2 è 1.
L'estrazione di un record da SQL*Plus, su tab2, restituisce come tempistica
(set timing on) questo valore:
Elapsed: 00:00:05.06
L'estrazione dello stesso record, su tab1, restituisce questa tempistica:
Elapsed: 00:00:42.06
A questo punto, se traggo delle conclusioni, ne deduco che:
1) con più extents la tabella è frammentata e perde prestazioni;
2) con un extent riesco ad avere risultati accettabili anche senza indici.
Ed è per questo che non riesco a comprendere appieno ciò che cerchi di
dirmi.
Henryx
P.S. l'estrazione delle clausole di storage e dello script di creazione
della
tablespace l'ho eseguita con Toad (personalmente, come clausole di storage,
inserisco solo MINEXTENTS, MAXEXTENTS e PCTINCREASE)
P.S. scusa se non sono più specifico, ma sono informazioni prese nell'ambito
lavorativo
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

Ciao Henryx,
la prima cosa che vedo e' la condizione della tablespace:
hai creato in una 9i una DMT invece di una LMT.
Questo ti fara' sempre perdere in performance e consiglio la pratica 
solo se hai un bug grave (tipo corruzione di dati) che puo' essere 
risolto solo con il vecchio modello di allocazione degli spazi.
Ti consiglio pertanto la ricreazione della tablespace.
Continuando: se non hai indici e' improbabile che ti servano le 
statistiche sulle tabelle ma e' sempre meglio averle.
Per le vecchie DMT c'e' un overhead sul numero di extent quindi le 
clausule di storage dovrebbero essere scelte per permettere un numero di 
extent nell'ordine del centinaio.
Ma ancora la differenza di prestazione puo' essere data da ben altro.
L'uso del termine "tabella frammentata" e' improprio. Il  numero di 
extent non rappresenta frammentazione.
Cio' che puo' fare la differenza e' su tu hai chained rows o migrated rows.
A questo punto una movimentazione dei blocchi attraverso una move 
dovrebbe risolverti il problema.
Ti chiedo quindi la prova: passa ad una LMT (ne acquisirai in 
performance e tempo di mantenimento) e movimenta i dati sulla due (poi 
ricalcola le statistiche).
Prendi quindi i tempi di esecuzione.
Lo stesso test e' stato fatto centinaia di volte per dimostrare come un 
unico segmento non incrementi le performance (comunque, anche nelle LMT 
puoi avere un degrado superando i 1000 extent).
Fabrizio
PS: Capisco perfettamente che tu non possa pubblicare qualcosa di 
riservato. Non preoccuparti.


 2) con un extent riesco ad avere risultati accettabili anche senza indici.
[...]
[interessante thread]
...le tue conclusioni non sono corrette.
In primis, la tua prova non dimostra (1) in quanto TU pensi che quella
sia l'unica differenza tra le due query.
Errato č l'approccio: se devi paragonare due query che insistono su due
segmenti differenti (volendo apprezzare la differenza di tuning del
segmento) ti DEVI assicurare che le query abbiano lo stesso piano di
esecuzione, che gli oggetti siano possibilmente o entrambi in BP o NON
in BP... e sopratutto devi analizzare i tempi di wait per capire dove
sono effettivamente le differenze. Mi viene in mente anche che il piano
di esecuzione anche se uguale puň non bastare, per esempio per via
dell'HWM.
La deduzione (2) č una deduzione che potrebbe essere corretta SES vai
esclusivamente in FTS o FFS (ma non ci puoi andare senza idx)  su un
segmento.
.g