Translation

The oldest posts, are written in Italian. If you are interested and you want read the post in English, please use Google Translator. You can find it on the right side. If the translation is wrong, please email me: I'll try to translate for you.

giovedì, agosto 04, 2011

Export, gzip and pipe

$for i in $(cat dwpr_test_01.list); do
>nohup ./export_dwpr_test.sh $i 2>&1 > $i.nohup &
>done

dove

$cat export_dwpr_test.sh
WORKINGDIR=/dwhtest01a/export.20110804
NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
ORACLE_BASE=/u1/app/oracle
ORACLE_SID=dwprt
ORACLE_TERM=vt100
ORA_NLS33=/u1/app/oracle/product/9.2.0/ocommon/nls/admin/data
ORACLE_HOME=/u1/app/oracle/product/9.2.0
ADMIN=system
PASSWORD=password
USERNAME=$1

rm ${WORKINGDIR}/${USERNAME}.pipe
mknod ${WORKINGDIR}/${USERNAME}.pipe p

gzip < ${WORKINGDIR}/${USERNAME}.pipe > ${WORKINGDIR}/${USERNAME}.dmp.gz &

exp $ADMIN/$PASSWORD OWNER=${USERNAME} FILE=${WORKINGDIR}/${USERNAME}.pipe LOG=${WORKINGDIR}/${USERNAME}_dwprt_export.log

rm ${WORKINGDIR}/${USERNAME}.pipe

$cat dwpr_test_01.list
PR_AI_INTEG
PR_AI_PRE
PR_DM_PRE
PR_EDW_COLL
PR_EDW_PRE
PR_LAY_PRE
PR_SRVDIFF_COLL
PR_SRVDIFF_PRE

martedì, agosto 02, 2011

KSV master wait message on ASM

A seguito di un crash di entrambe le istanze di un RAC, ho aperto una Service Request su metalink. Più sotto c'è la risposta.

Ecco le cose interessanti:

  1. "KSV master wait" event, indicates the process on the RDBMS side is waiting for a reply from a process on the ASM side.
  2. "ASM file metadata operation" is a wait envet generated by a database remote process (in this case, the database ABC is the clinet)
  3. SIGLOST: SIG is a common prefix for signal names. LOST refers to a lost file lock.

=========
Support note
=========
According to the systemstate dump, from the instance, the majority of the background processes are found dead and last wait for service name: SYS$BACKGROUND , is for 'KSV master wait' . Event 'KSV master wait' indicates the process on the RDBMS side is waiting for a reply from a process on the ASM side.

In both ASM instances, ORA-07445 is being dumped , right before notifying the death of the corresponding instance:

Sun Jul 24 14:45:03 2011
NOTE: ASM client ABCp1:ABCp died unexpectedly.

According to the trace file, it was generated by a remote process waiting for 'ASM file metadata operation'. The call stack of the ORA-07445 is generic and per trace file, "Process received SIGLOST. Therefore the callstack does not point to the location of the problem." However, the callstack contains a hint, and that is the tcpip function, which could point to a problem at the network level.

Given the data above, please check with your system administrator if there's any network issue that could have interrupted the communication between the database and the ASM instances, and let me know the results.

======================
== ODM Data Collection ==
======================

Dump file /sbRdbms/app/oracle/diag/asm/+asm/+ASM1/incident/incdir_17865/+ASM1_ora_5029906_i17865.trc
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
ORACLE_HOME = /sbRdbms/app/oracle/product/ASM
System name: AIX
Node name: abcdbs01
Release: 1
Version: 6
Machine: 00CD96944C00
Instance name: +ASM1
Redo thread mounted by this instance: 0
Oracle process number: 33
Unix process pid: 5029906, image: oracle@abcdbs01 (TNS V1-V3)


*** 2011-07-24 14:45:00.080
*** SESSION ID:(83.3) 2011-07-24 14:45:00.080
*** CLIENT ID:() 2011-07-24 14:45:00.080
*** SERVICE NAME:() 2011-07-24 14:45:00.080
*** MODULE NAME:(oracle@abcdbs01 (TNS V1-V3)) 2011-07-24 14:45:00.080
*** ACTION NAME:() 2011-07-24 14:45:00.080

Dump continued from file: /sbRdbms/app/oracle/diag/asm/+asm/+ASM1/trace/+ASM1_ora_5029906.trc
ORA-07445: exception encountered: core dump [_ptrgl()] [SIGSEGV] [ADDR:0x7F8000007FC00000] [PC:0x10000DE98] [Address not mapped to object] []

========= Dump for incident 17865 (ORA 7445 [_ptrgl()]) ========
----- Beginning of Customized Incident Dump(s) -----
Exception [type: SIGSEGV, Address not mapped to object] [ADDR:0x7F8000007FC00000] [PC:0x10000DE98, _ptrgl()]
Registers:
iar: 0x000000010000de98 lr: 0x0000000102274170
msr: 0xa00000000000d032 cr: 0x0000000024202220
r00: 0x0000000000000028 r01: 0x0fffffffffff9250 r02: 0x0000000110352700
r03: 0x0fffffffffffaf50 r04: 0x0000000000000140 r05: 0x0000000000002683
r06: 0x0000000000000001 r07: 0x0000000000000005 r08: 0x00000000ffff9450
r09: 0x0fffffffffff9348 r10: 0x0700000010f9d400 r11: 0x7f8000007fc00000
r12: 0x0000000044202220 r13: 0x00000001103a8e18 r14: 0x0000000000000000
r15: 0x0fffffffffffac48 r16: 0x00000000000001d5 r17: 0x0000000110282a98
r18: 0x0fffffffffffb104 r19: 0x00000001100caa28 r20: 0x000000010762e2b0
r21: 0x0000000000000000 r22: 0x00000000000000b8 r23: 0x0000000000000000
r24: 0x000000000000008f r25: 0x0000000107d164d8 r26: 0x0000000000000000
r27: 0x00000001100cab80 r28: 0x0fffffffffff9a20 r29: 0x0700000000003640
r30: 0x000000010859bee8 r31: 0x0fffffffffffaf50

*** 2011-07-24 14:45:00.080
----- SQL Statement (None) -----
Current SQL information unavailable - no cursor.

----- Call Stack Trace -----
calling call entry argument values in hex
location type point (? means dubious value)
-------------------- -------- -------------------- ----------------------------
opiodr ttcpip opitsk opiino opiodr opidrv sou2o opimai_real main start

....................

Argument/Register addr=0x1078833c2.
Dump of memory from 0x107883382 to 0x1078834c2
107883380 7820206C 723A2030 78253031 366C780A [x lr: 0x%016lx.]
107883390 0049424D 6D73723A 20307825 3031366C [.IBMmsr: 0x%016l]
1078833A0 78202063 723A2030 78253031 36780A00 [x cr: 0x%016x..]
1078833B0 72253032 643A2030 78253031 366C7825 [r%02d: 0x%016lx%]
1078833C0 63000A00 00000000 00000000 4E4F5449 [c...........NOTI]
1078833D0 43453A20 50726F63 65737320 72656365 [CE: Process rece]
1078833E0 69766564 20736967 6E616C20 5349474C [ived signal SIGL]
1078833F0 4F53542E 20546865 7265666F 72652C20 [OST. Therefore, ]
107883400 74686520 63616C6C 0A202020 20202020 [the call. ]
107883410 20737461 636B2064 6F657320 6E6F7420 [ stack does not ]
107883420 706F696E 7420746F 20746865 206C6F63 [point to the loc]
107883430 6174696F 6E206F66 20746865 2070726F [ation of the pro]
107883440 626C656D 2E0A0A00 0A457863 65707469 [blem.....Excepti]
107883450 6F6E205B 74797065 3A202573 2C202573 [on [type: %s, %s]
107883460 5D205B41 4444523A 3078256C 585D0049 [] [ADDR:0x%lX].I]
107883470 205B5043 3A307825 6C582C20 0049424D [ [PC:0x%lX, .IBM]
107883480 7B656D70 74797D00 25735D00 205B6578 [{empty}.%s]. [ex]
107883490 63657074 696F6E20 69737375 65642062 [ception issued b]
1078834A0 79207069 643A2025 642C2075 69643A20 [y pid: %d, uid: ]
1078834B0 25645D00 50433A30 78256C58 0049424D [%d].PC:0x%lX.IBM]
1078834C0 41444452 [ADDR]
.....................

----------------------------------------
SO: 0x700000010f9b9e0, type: 4, owner: 0x700000010e692d0, flag: INIT/-/-/0x00 if: 0x3 c: 0x3
proc=0x700000010e692d0, name=session, file=ksu.h LINE:10719 ID:, pg=0
(session) sid: 83 ser: 3 trans: 0x0, creator: 0x700000010e692d0
flags: (0x41) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
flags2: (0x8) -/-
DID: , short-term DID:
txn branch: 0x0
oct: 0, prv: 0, sql: 0x0, psql: 0x0, user: 0/SYS
ksuxds FALSE at location: 0
service name: SYS$USERS
client details:
O/S info: user: oracle, term: , ospid: 1716314
machine: abcdbs01 program: oracle@abcdbs01 (TNS V1-V3)
application name: oracle@abcdbs01 (TNS V1-V3), hash value=335489673
Current Wait Stack:
0: waiting for 'ASM file metadata operation'
msgop=28, locn=1, =0
wait_id=5596 seq_num=9859 snap_id=1
wait times: snap=2.076467 sec, exc=2.076467 sec, total=2.076467 sec
wait times: max=infinite
wait counts: calls=0 os=0
in_wait=1 iflags=0x5a0
Wait State:
auto_close=0 flags=0x22 boundary=0x0/-1
Session Wait History:
0: waited for 'SQL*Net message from client'
driver id=62657100, #bytes=1, =0
wait_id=5595 seq_num=9858 snap_id=1
wait times: snap=4.945453 sec, exc=4.945453 sec, total=4.945453 sec
wait times: max=infinite
wait counts: calls=0 os=0
occurred after 0.000004 sec of elapsed time
1: waited for 'SQL*Net message to client'
driver id=62657100, #bytes=1, =0
wait_id=5594 seq_num=9857 snap_id=1

Backup on Netezza

1. Creazione del database

SYSTEM(ADMIN)=> create database as_test;
CREATE DATABASE

Il database "as_test" non ha tabelle

2. Backup del database

[nz@dwhntzc SalzanoA]$ nz_backup -host dwhntzc -format binary -dir /dwhntzc_fs/SalzanoA/bck_asTest -db as_test

nz_backup of database AS_TEST started on 2011-08-02 12:18:19

NZ_HOST: dwhntzc
NZ_USER: ADMIN
NZ_DATABASE: AS_TEST
Backup Directory: /dwhntzc_fs/SalzanoA/bck_asTest
Backup Format: binary
Custom Script:
# Of Threads: 1
Using stableTXid: 24582039
The lastTXid assigned was: 24582040

=========================================================================

ERROR: 0 tables were processed !!
It would appear that there are no tables defined in the database that
is being backed up (or restored). Or, perhaps this database account
doesn't have access to those tables.

=========================================================================

nz_backup of database AS_TEST finished on 2011-08-02 12:18:19

Total # of tables processed: 0
Total # of seconds elapsed : 0

=========================================================================

3. Creazione di una tabella

[nz@dwhntzc SalzanoA]$ nzsql -E as_test
********* QUERY *********
select current_catalog, current_user
*************************

SYSTEM(ADMIN)=> \c as_test asalzano a$a7zan0
You are now connected to database as_test as user asalzano.
********* QUERY *********
select current_catalog, current_user
*************************

AS_TEST(ASALZANO)=> create table as_mytab (one integer);
CREATE TABLE

[nz@dwhntzc SalzanoA]$ nz_backup -host dwhntzc -format binary -dir /dwhntzc_fs/SalzanoA/bck_asTest -db as_test

nz_backup of database AS_TEST started on 2011-08-02 13:38:39

NZ_HOST: dwhntzc
NZ_USER: ADMIN
NZ_DATABASE: AS_TEST
Backup Directory: /dwhntzc_fs/SalzanoA/bck_asTest
Backup Format: binary
Custom Script:
# Of Threads: 1
Using stableTXid: 24582153
The lastTXid assigned was: 24582154

=========================================================================

Info: table 1 of 1 AS_MYTAB
Info: backup process started 2011-08-02 13:38:39
Info: estimated # of records 0
Info: unloading data ( thread 1 of 1 )
Info: data flowing ...
Info: unload finished ( thread 1 of 1 ) seconds 0
Info: unload results ( thread 1 of 1 ) INSERT 0 0
Info: data flow finished
Info: backup process ended 2011-08-02 13:38:39
Info: # of records unloaded 0
Info: # of seconds elapsed 0

=========================================================================

nz_backup of database AS_TEST finished on 2011-08-02 13:38:39

Total # of tables processed: 1
Total # of records unloaded: 0
Total # of seconds elapsed : 0

=========================================================================

Managing privileges on Netezza

[nz@dwhntzc SalzanoA]$ nzsql -E
********* QUERY *********
select current_catalog, current_user
*************************

SYSTEM(ADMIN)=> grant connect on as_test to asalzano;
GRANT

SYSTEM(ADMIN)=> grant create table to asalzano;
GRANT

SYSTEM(ADMIN)=> \c as_test asalzano xxxxxx
You are now connected to database as_test as user asalzano.
********* QUERY *********
select current_catalog, current_user
*************************

AS_TEST(ASALZANO)=> create table as_mytab (one integer);
CREATE TABLE

lunedì, luglio 25, 2011

Transaction Rollback Monitoring

V$FAST_START_TRANSACTIONS displays information about the progress of the transactions that Oracle is recovering.

alter session set nls_date_format='dd/mm/yyyy hh24:mi:ss';

select usn, state, undoblockstotal "Total", undoblocksdone||' ('||round(UNDOBLOCKSDONE/UNDOBLOCKSTOTAL*100,2)||'%)' "Done",
 undoblockstotal-undoblocksdone "ToDo",
         decode(cputime,0,'unknown',sysdate+(((undoblockstotal-undoblocksdone) / (undoblocksdone / cputime)) / 86400))||' ('|| round((undoblockstotal-undoblocksdone)/UNDOBLOCKSDONE*CPUTIME/3600,2)||'h)' "Estimated time to complete"
  from v$fast_start_transactions;

USN STATE Total Done ToDo Estimated time to complete
63
RECOVERING
349526
194208 (55,56%)
155318
27/07/2011 16:34:04 (20,25h)
86
RECOVERING
309253
194095 (62,76%)
115158
27/07/2011 11:20:29 (15,02h)

Database Hangs Because SMON is taking 100% CPU doing transaction recovery [ID 414242.1]
How to Disable Parallel Transaction Recovery When Parallel Txn Recovery is Active [ID 238507.1]
Rollback Is Taking A Long Time After Session Killed [ID 1060831.6]
How Long Will My Rollback Take? Is my Transaction Doing Anything? [ID 169138.1]

venerdì, luglio 22, 2011

SQL Tuning Sets

A SQL Tuning Set (STS) is a database object that includes one or more SQL statements along with their execution statistics and execution context, and could include a user priority ranking. The SQL statements can be loaded into a SQL Tuning Set from different SQL sources, such as the Automatic Workload Repository, the cursor cache, or custom SQL provided by the user.

An STS includes:
  • A set of SQL statements
  • Associated execution context, such as user schema, application module name and action, list of bind values, and the cursor compilation environment
  • Associated basic execution statistics, such as elapsed time, CPU time, buffer gets, disk reads, rows processed, cursor fetches, the number of executions, the number of complete executions, optimizer cost, and the command type
  • Associated execution plans and row source statistics for each SQL statement (optional)
A SQL Tuning Set can be used as input to the SQL Tuning Advisor, which performs automatic tuning of the SQL statements based on other input parameters specified by the user. SQL Tuning Sets are transportable across databases and can be exported from one system to another, allowing for the transfer of SQL workloads between databases for remote performance diagnostics and tuning. To transport SQL Tuning Sets, use the DBMS_SQLTUNE package procedures.

(Performance Tuning Guide - Ch12.9)

Choosing an Access Path

To choose an access path, the optimizer first determines which access paths are available by examining the conditions in the statement's WHERE clause and its FROM clause. The optimizer then generates a set of possible execution plans using available access paths and estimates the cost of each plan, using the statistics for the index, columns, and tables accessible to the statement. Finally, the optimizer chooses the execution plan with the lowest estimated cost.

When choosing an access path, the optimizer is influenced by the following:
  • Optimizer hints: The optimizer's choice among available access paths can be overridden with hints. (Using hints requires changing the code)
  • Statistics: For example, if a table has not been analyzed since it was created, and the table statistics show that it is small, then the optimizer uses a full table scan. The LAST_ANALYZED and BLOCKS columns in the ALL_TABLES table reflect the statistics used by the optimizer.
  • SQL outlines, SQL baseline plans, and SQL profiles: If these exist they will override the optimizer choices. For more information see the SQL Performance Management lesson.
(Oracle Database 11g: Performance Tuning Ch10.17)

giovedì, luglio 21, 2011

Hierarchical Queries

Come ottenere un result set utilizzando query gerarichiche.

SELECT LPAD(' ', LEVEL*2)||columnX
FROM table
WHERE condition(s)
START WITH condition(s)
CONNECT BY PRIOR column1 = column2
ORDER SIBLINGS BY columnX;

Ci sono due modi di ricevere i dati (il top-down coincide con la visita in ordine anticipato di un albero):

=======
Top down
=======
column1 = Parent Key
column2 = Child Key

=======
Bottom up
=======
column1 = Child Key
column2 = Parent Key

The direction of the query, whether it is from parent to child or from child to parent, is determined by the CONNECT BY PRIOR column placement. The PRIOR operator refers to the parent row. To find the child rows of a parent row, the Oracle server evaluates the PRIOR expression for the parent row and the other expressions for each row in the table. Rows for which the condition is true are the child rows of the parent. The Oracle server always selects child rows by evaluating the CONNECT BY condition with respect to a current parent row.
(11g SQL Fundamentals II - App F.7)

You have to be careful when trying to order the rows of output in a hierarchical query. By default, if you omit the ORDER BY clause altogether, the query attempts to sort rows in an order that’s reflective of the hierarchy. Display will start first with a LEVEL 1 row. If that row is superior to any LEVEL 2 rows, those rows will display next before another LEVEL 1 row displays. The same approach is taken at LEVEL 2, so that rows will display down to leaf node levels before the next rows show at the higher levels. The result is a display that is meaningful to the hierarchy. But if you try to order these rows with the ORDER BY clause, you’ll create a syntactically correct statement that probably doesn’t help you much. ORDER SIBLINGS sorts rows within each given level, not across levels, thus retaining the hierarchical relationship across rows of output. Note that our earlier use of ORDER BY did not create an error message, just misleading output
(OCA Oracle Database SQL Certified Expert Exam Guide)

Per esempio, il top-down:

SELECT LPAD(' ', LEVEL*2)||last_name
FROM employees
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name;

Userò il concetto di query gerarchiche in due casi:
  1. lock
  2. parallel query

venerdì, luglio 15, 2011

Modify dos windows colours

Questi i parametri della finestra dos utilizzati da Power Shell

Layout: Dimensioni buffer dello schermo
Larghezza 120
Altezza 3000

Layout: Dimensioni finestra
Larghezza 120
Altezza 52

Layout: Posizione finestra
Sinistra 201
Alto 18

Colori: Testo normale
Rosso 255
Verde 255
Blu 255

Colori: Sfondo normale
Rosso 1
Verde 36
Blu 86

Colori: Testo popup
Rosso 128
Verde 0
Blu 128

Colori: Sfondo popoup
Rosso 255
Verde 255
Blu 255

giovedì, luglio 14, 2011

How to change language of SQL Developer

Nella direcotry "bin" di SQL Developer, aprire il file "sqldeveloper.conf" ed aggiungere o modificare le seguenti due righe:
 
AddVMOption -Duser.language=en
AddVMOption -Duser.country=US
 
Una volta fatto, chiudere e riavviare l'applicazione.

Questo il link originale: How to change the language of SQL Developer's user interface?

Di seguito due immagini utili a mostrare le modifiche da fare.



Create new user and assign grant

[nz@dwhtwf01 ~]$ nzsql
Welcome to nzsql, the Netezza SQL interactive terminal.

Type:  \h for help with SQL commands
       \? for help on internal slash commands
       \g or terminate with semicolon to execute query
       \q to quit

SYSTEM(ADMIN)=> CREATE USER sarusso WITH PASSWORD 'please_change_me';
CREATE USER

SYSTEM(ADMIN)=> ALTER GROUP group_dev ADD USER sarusso;
ALTER GROUP

SYSTEM(ADMIN)=> ALTER GROUP group_analyst ADD USER sarusso;
ALTER GROUP



SYSTEM(ADMIN)=> \c NTZ_DWDMP
You are now connected to database NTZ_DWDMP.

NTZ_DWDMP(ADMIN)=> GRANT LIST ON TABLE TO sarusso;
GRANT

NTZ_DWDMP(ADMIN)=> GRANT SELECT ON TABLE TO sarusso;
GRANT



NTZ_DWDMP(ADMIN)=> \c NTZ_DWDMS
You are now connected to database NTZ_DWDMS.

NTZ_DWDMS(ADMIN)=> GRANT LIST ON TABLE TO sarusso;
GRANT

NTZ_DWDMS(ADMIN)=> GRANT SELECT ON TABLE TO sarusso;
GRANT



NTZ_DWDMS(ADMIN)=> \c NTZ_DWSAS
You are now connected to database NTZ_DWSAS.

NTZ_DWSAS(ADMIN)=> GRANT LIST ON TABLE TO sarusso;
GRANT

NTZ_DWSAS(ADMIN)=>  GRANT SELECT ON TABLE TO sarusso;
GRANT

NTZ_DWSAS(ADMIN)=> \q

mercoledì, giugno 22, 2011

Who is blocking me?

col username for a25
col IS_BLOCKED_BY for a20
col state for a40
col sql_id for a15
col obj for a80
set lines 220
set trim on

select
  nvl(USERNAME,schemaname)||' ('||SID||':'||INST_ID||')' USERNAME
 ,SQL_ID
 ,nvl2(BLOCKING_SESSION,BLOCKING_SESSION||':'||BLOCKING_INSTANCE||':'||
   (select
      sql_id
    from
      gv$session holder
    where
      holder.inst_id= s.BLOCKING_INSTANCE
    and holder.sid=s.BLOCKING_SESSION), null) IS_BLOCKED_BY
 ,decode(state, 'WAITING', 'WAITING', 'ON CPU')||'
 ('||substr(event,1,40)||')' state
 ,ROW_WAIT_FILE#||':'||ROW_WAIT_BLOCK#||':'||ROW_WAIT_ROW#||'
'||case
    when ROW_WAIT_OBJ# >0 then
     (select owner||':'||object_name||':'||nvl(subobject_name,'=nosub=')||' ('||object_type||')'
      from
       dba_objects do
      where
       do.object_id=s.ROW_WAIT_OBJ#)
  end obj
from
  gv$session s
where
  event in
    (select
       NAME
     from
       v$event_name
     where
       WAIT_CLASS != 'Idle')
order by sid;

martedì, giugno 21, 2011

Format on Windows 7 [1]

From dos window:

DISKPART
LIST DISK
SELECT DISK # (USB Stick)
CLEAN ALL
CREATE PARTITION PRIMARY
SELECT PARTITION 1
ACTIVE
FORMAT FS=FAT32
ASSIGN
EXIT
EXIT


[1] http://www.sevenforums.com/hardware-devices/61770-cannot-format-usb-flash-drive.html

lunedì, giugno 20, 2011

Single quotes and double quote

Che differenza c'è tra gli apici singoli e quelli doppi in bash?

Semplicemente, nel primo caso la shell non interpreta le variabili, cosa che invece fa nel secondo. In altri termini, nel secondo caso, la shell sostituisce la variabile con il suo valore.

=========
Apici singoli
=========
[my-lap]$ var1=pippo
[my-lap]$ var2='$var1 & pluto'
[my-lap]$ echo $var2
$var1 & pluto

=========
Apici doppi
=========
[my-lap]$ var1=pippo
[my-lap]$ var3="$var1 & pluto"
[my-lap]$ echo $var3
pippo & pluto

domenica, giugno 19, 2011

Workload

Vediamo il significato di workload, preso direttamente dal dizionario:

Workload – The amount of work that a machine produces or can produce in a specified time period [1]

ovvero il "workload" rappresenta la quantità di lavoro che una macchina produce o può produrre nell'unità di tempo. E' una definizione interessante a cui però occorre presrestare attenzione. Il termine "macchina", anche se menzionato, non ha nulla a che fare con un computer o con un database. Qui, la "macchina" è pensata come statica e pertanto non c'è la possibilità di migliorare le prestazioni. Per una fotocopiatrice ad esempio, indipendentemente dalla risma di carta utilizzata o dal numero di copie da produrre, il lavoro svolto è costante.

Quando lavoriamo con i computer, il workload assume tutt'altro significato. Il carico di lavoro, nella sua definizione più generale, è il numero totale di richiesete che arrivano su di un sistema. Nel caso di un database, questo vuol dire che il workload è l'insieme degli statement SQL che, indipendentemente dalla loro esecuzione, arrivano su un'istanza e danno una risposta agli utenti che li hanno sottomessi.

E' chiaro che questo è un concetto duro da accettare perché per "insieme degli statement SQL che arrivano su un istanza" si intende proprio tutto l'SQL: sia quello visibile che quello non visibile. Ed in fondo è difficile fare il tuning dell'invisibile.

Dobbiamo allora utilizzare una definizione più ampia di workload considerando ciò che il database vede indipendentemente da quello che succede al di fuori del database stesso. Questo vuol dire campionare, misurare, tracciare quelle statistiche, all'interno dell'RDBMS, che misurano, quantificano o caratterizzano cosa sia il workload. Ed è fondamentale non solo scegliere quelle che lo misurano ma anche considerare quelle che non dipendono dalle performance del db. Statistiche come "CPU usage", "elapsed time" ed i vari "wait event" non sono buoni esempi di misura del workload poiché dipendono ampiamente dal sistema su cui gli statement SQL stano girando. Metriche più appropriate potrebbero invece essere quelle di gruppo come "numero di esecuzioni di SQL", "active session", "users" etc.

E' chiaro che mentre la scelta delle metriche deve essere indipendente da quanto avviene fuori dal db, ciò che misuriamo lo deve invece essere. Voglio dire che, quando definiamo un workload, al di là dalla metrica utilizzata, dobbiamo essere sicuri che quello che stiamo tracciando sia correlato alle risorse consumate all'interno del database. In questo possiamo allora dire, in base all'aumento o alla diminuzione del workload, qual è o quale sarà l'impatto sulle performance percepito.




[1] What Is Your Definition of Database Workload?

mercoledì, giugno 15, 2011

Metrics

Le metriche mantengono traccia di differenti eventi durante la vita del database [1]. Queste sono visibili da GV$METRICNAME.METRIC_NAME.

Sono statistiche che misurano la variazione dei cambiamenti in statistiche di performance comulative [2]. L'idea di base è la seguente [5]:

Tra di esse troviamo: "CPU Usage Per Sec", "Elapsed Time Per User Call", "Host CPU Utilization", etc.

Prendo un valore V1, all'istante T1 ed uno V2, all'istante T2. A questo punto, la metrica è definita come rapporto (V2 – V1) / (T2 – T1). AWR le raccoglie automaticamente. Frequenza della raccolta e retention dei dati, sono specificati in DBA_HIST_WR_CONTROL

SELECT snap_interval, retention FROM dba_hist_wr_control;

SNAP_INTERVAL
-------------------------------------
RETENTION
-------------------------------------
+00000 01:00:00.0
+00007 00:00:00.0

(profondità di 7 giorni, con raccolta ogni ora) e la modifica è possibileattraverso la funzione DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS

BEGIN
  dbms_workload_repository.modify_snapshot_settings(
  interval => 60,
  retention => 10*24*60
  );
END;


Sono collezionate ogni minuto, storicizzate in memoria e quindi salvate nelle tabelle WRH$ (H=History) di AWR (il tablespace su cui risiedono è SYSAUX). Complessivamente, sono disponibili le seguenti [3][5]:

Table: Global
VIEW/TABLE
GV$METRIC
GV$METRIC_HISTORY

Table: Information
VIEW/TABLE
GV$METRICGROUP
GV$METRICNAME
DBA_HIST_METRIC_NAME
WRH$_METRIC_NAME

Sono disponibili per [5]

» System
» Sessions
» Services
» Events
» Files

e raggruppate come di seguito:

select GROUP_ID, GROUP_NAME from V$METRICGROUP order by GROUP_ID

  GROUP_ID GROUP_NAME
---------- -------------------------------------------
         0 Event Metrics
         1 Event Class Metrics
         2 System Metrics Long Duration
         3 System Metrics Short Duration
         4 Session Metrics Long Duration
         5 Session Metrics Short Duration
         6 Service Metrics
         7 File Metrics Long Duration
         9 Tablespace Metrics Long Duration
        10 Service Metrics (Short)

Ed in V$METRICNAME.METRIC_UNIT, troviamo l'unità di misura in cui viene espressa quella particolare metrica. Sono espresse per

» Valori assoluti
» Percentuali
» Per secondi e per transactioni

Ad esempio:

select group_id id, metric_name, metric_unit from v$metricname where group_id=1

  ID METRIC_NAME                         METRIC_UNIT
---- -------------------------------     -----------
   1 Total Wait Counts                   Waits
   1 Total Time Waited                   CentiSeconds
   1 Database Time Spent Waiting (%)     % (TimeWaited / DBTime)
   1 Average Users Waiting Counts        Users


I valori degli utli 10 minuti sono visibili dalle GV$*, quelle degli utlimi 10+60 minuti dalle GV$*_HISTORY e quelle con retention superiore dalle DBA_HIST_* (le sottostanti tabelle sono le WRH$*). Le viste di sistema disponibili sono:

Table: Events
GROUP_ID VIEW/TABLE
0 GV$EVENTMETRIC
1 GV$WAITCLASSMETRIC
GV$WAITCLASSMETRIC_HISTORY
WRH$_WAITCLASSMETRIC_HISTORY

Table: System
GROUP_ID VIEW/TABLE
2/3 GV$SYSMETRIC
GV$SYSMETRIC_HISTORY
GV$SYSMETRIC_SUMMARY
DBA_HIST_SYSMETRIC_HISTORY
DBA_HIST_SYSMETRIC_SUMMARY
WRH$_SYSMETRIC_HISTORY
WRH$_SYSMETRIC_SUMMARY

Table: Session
GROUP_ID VIEW/TABLE
4/5 V$SESSMETRIC
DBA_HIST_SESSMETRIC_HISTORY
WRH$_SESSMETRIC_HISTORY

Table: Service
GROUP_ID VIEW/TABLE
6/10 GV$SERVICEMETRIC
GV$SERVICEMETRIC_HISTORY

Table: Files
GROUP_ID VIEW/TABLE
7 GV$FILEMETRIC
GV$FILEMETRIC_HISTORY
DBA_HIST_FILEMETRIC_HISTORY
WRH$_FILEMETRIC_HISTORY

Per il GROPU_ID 9 della V$METRICGROUP, non ho trovato associazioni. Suppongo, visto che si tratta di tablespace, che le corrispondenti metriche si potrebbero associare a quelle per "Files".

GROUP_ID VIEW/TABLE
9

[1] Oracle Metrics
[2] Database Metrics
[3] AUTOMATED WORKLOAD REPOSITORY
[4] AWR Metrics
[5] Automatic Workload Repository


Post update 2011/06/16

lunedì, giugno 13, 2011

puser

Quali processo stanno utilizzando la porta del listener? Linux permette di rispondere a questa domanda utilizzando il comando fuser con l'opzione "-n". Il programma che segue è scritto in perl ed è necessario avere i privilegi di accesso a tutte le sottodirectory di /proc. Per utilizzarlo basta lanciare “puser” seguito dal numero della porta da controllare. Ad esempio:

#andrea> puser 1531
1531: 2506 18359

#!/usr/bin/perl
die "Usage: puser \n" if @ARGV[0] == 0;

$ENV{'PORT'} = @ARGV[0];
$shell_in = <<'IN'; echo "" > /tmp/checkPortTestPerl;

for PROC in /proc/*; do
  echo $PROC >> /tmp/checkPortTestPerl 2> /dev/null
  pfiles -F $PROC | grep port |grep $PORT >> /tmp/checkPortTestPerl 2> /dev/null

done 2> /dev/null

IN

$shell_out = `$shell_in`;
open(FH, "< /tmp/checkPortTestPerl") or die "can't open /tmp/checkPortTestPerl: $!";

$i=0;
$lineprep=;

for ($count=0; $row=; $count++) {
  if ($row =~ m/@ARGV[0]/){
    $lineprep =~ m#^/[a-z]+/([0-9]+)$#;
    $process[$i]=$1;

    $i++;
  }
  $lineprep=$row;
}

print "@ARGV[0]: @process\n";
unlink "/tmp/checkPortTestPerl";

Time Zone

Riporto questo documento che scrissi nel 2005

domenica, giugno 12, 2011

set events 10053

Alcuni eventi come il 10053, hanno bisogno del privilegio esplicito di ALTER SESSION.

* Creiamo innanzitutto un utente:

wedosas01.RAIDTRN(SYS)> create user pippo identified by pippo;
User created.

wedosas01.RAIDTRN(SYS)> grant connect to pippo;
Grant succeeded.

* Proviamo ad abilitare l'evento 10053

wedosas01.RAIDTRN(SYS)> conn pippo/pippo
Connected.

wedosas01.RAIDTRN(PIPPO)> alter session set events '10053 trace name context forever , level 1';

ERROR:
ORA-01031: insufficient privileges

* Assegnamo allora esplicitamente il privilegio di ALTER SESSION...

wedosas01.RAIDTRN(PIPPO)> conn / as sysdba
Connected.

wedosas01.RAIDTRN(SYS)> grant alter session to pippo;
Grant succeeded.

* ...e riproviamo ad abilitarlo nuovamente

wedosas01.RAIDTRN(SYS)> conn pippo/pippo
Connected.

wedosas01.RAIDTRN(PIPPO)> alter session set events '10053 trace name context forever , level 1';
Session altered.

venerdì, ottobre 24, 2008

Perfect!

Tre! Tre è il numero perfetto.

In 3 categorie, possiamo classificare i lock:

1. Lock di tipo applicativo
2. Latch sul Dizionario Dati
3. Latch sulle strutture dati di memoria

In 3 categorie possiamo schematizzare le operazioni fatte sulla Buffer Cache:

1. Ricerca (di un blocco in memoria)
2. Modifica/Sostituzione (del blocco ricercercato al punto 1)
3. Scrittura su disco (del blocco modificato al punto 2)

In 3 categorie possiamo raggruppare le informazioni raccolte dalle viste di sistema [Lewis:

1. Persone (v$sesstat, v$session_event, v$sess_time_model)
2. Risorse (v$filestat, v$segstat, v$latch, v$event_histogram)
3. Statement (v$sql, v$sqlstats)

come 3 sono i punti di vista da cui puoi guardare le problematiche:

1. Utente/Sistema
2. Storico
3. In tempo reale

In 3 categorie possiamo raggruppare come viene speso il tempo in Oracle:

1. Prentendo un latch (spinning o sleepling)
2. Mantenendo un latch (lavoro su CPU)
3. Rilasciare un latch (lavoro su CPU)

3 sono gli statement di modifica:

1. Insert
2. Update
3. Delete

3 sono le certificazioni:

1. OCA
2. OCP
3. OCM

Ed infine, 3 sono le leggi a cui un DBA deve sottostare.

Insomma se 3 è il numero perfetto e si adatta bene ad Oracle, vuoi vedere che sotto sotto.....

=================
Update - 04/12/2008
=================

3 sono le maggiori componenti del framework [OCA-CRS-01] per la gestione del db:

1. Istanza, che deve essere gestita
2. Listenser, che consente le connessioni al DB
3. Enterprise Manager, che consente una gestione centralizzata dei database

3 sono le cose che un bravo DBA deve saper utilizzare:
1. vi
2. SQL*Plus
3. RMAN

Sono 3 gli insiemi (di directories) [OCA-ALL-01] che lo standard OFA prevede siano utilizzati per facilitare la gestione del database:

1. Uno per la raccolta dei binari
2. Uno per la raccolta dei files di amministrazione, control files e redolog (archiviati)
3. Uno per la raccolta dei datafiles

Riferimenti:
========
Conquering Oracle Latch Contention - http://www.orapub.com/
How to do Trouble-Shooting - http://www.jlcomp.demon.co.uk/
[OCA-CRS-01] Oracle Database 10g: Administrator Workshop 1, Cap4
[OCA-ALL-01] Oracle Database 10g Certification All-in-One Exam Guide, Parte1, Cap2

martedì, ottobre 14, 2008

Too Many Secrets: Introduzione

A grandi linee possiamo dividere un database in 2 parti distinte: quella su file system (che prende il nome di database) e quella in memoria: la SGA.

La SGA è a sua volta, divisa in 2: processi di background (pmon, smon, etc) e pools (di buffer) tra cui troviamo la Buffer Cache, lo Shared Pool ed il Log Buffer (esistono altre aree in SGA, ma per semplicità, le ometto) [cosmus01].

Alcune domande.

  • La ricerca in Buffer Cache come avviene?
  • Ok, lo statement è nello Shared Pool, ma il suo piano di esecuzione dove lo trovo? Visto che "select * from dual" è diverso da "SELECT * FROM DUAL", dove trovo queste informazioni? Ma sono proprio statement diversi? In fondo a parte la differenza di capitalizzazione, sono proprio la stessa cosa.
  • Bhé si, le "entry di redo" sono scritte in Log Buffer, ma come fa Oracle ad essere sicuro che che la scrittura sia avvenuta?

Ciò che dobbiamo approfondire è quindi:

  1. Buffer Cache

  2. Shared Pool

  3. Log Buffer

In realtà, esiste un punto 0 che va considerato e senza il quale non è possibile proseguire:

  1. Latch
[cosmus01] Sul sito Kosmus, esiste un dettaglio sull'architettura di Oracle 9i. 10g modifica alcune cose aggiungendo ad esempio nuovi processi di backgroud. Tuttavia, tali modifiche non cambiano quanto detto.

venerdì, ottobre 19, 2007

Statspack, forse non tutti sanno che.....

Conosco qualche DBA che dello Statspack ne ha fatto una ragione di vita, come se da esso si potessero individuare e risolvere tutti i problemi di performance legati ad un'istanza.

Premetto di essere il primo ad utilizzarlo per capire cosa c'è che non va studiando l'output che esso genera. Tuttavia, a mio avviso, Statspack deve essere un punto di partenza e non uno di arrivo.

Forse sarebbe più corretto dire che ne determinare problemi di performance, l'output più che guardarlo, andrebbe letto.

Spero di riuscire a chiarire il concetto.


1. Aggregazione dei dati
La funzionalità di base di Statspack è quella di fare due istatntanee dell'istanza in due momenti diversi; quindi si calcolano le differenze ed ne viene mostrato il risultato.

Questo però comporta un'aggregazione di dati. Purtroppo da un aggregato non è possibile estrarre un particolare.

Faccio un esempio. Se ho 100 palline che pesano 100 grammi, dico che ogni pallina pesa 1 grammo. Ma se di queste 100, 99 fossero nere ed 1 bianca, posso ancora dire che una sola pesa 1 grammo? In questo caso, l'informazione aggragata che tutte insieme pesano 100g non è sufficiente: per determinare il peso di ogni singola pallina devo necessariamente pesarle (i).

In Oracle succede una cosa analoga. L'output di Statspack mi dice che ci sono stati problemi di latching, di hard parsing, etc, ma non mi dice chi ne è stato la causa.


2. Heisemberg
Statspack è scritto in PL/SQL: quando vengono calcolati gli snapshot, vengono fatte query sul dizionario dati. In questo modo, secondo il Principio di Indeterminazione di Heisemberg, Statspak (l'osservatore) influenza l'istanza (l'osservato). Oracle 10g, cambia punto di vista: l'RDBMS stesso popola la base dati di AWR (ii).


3. Metriche inesatte
Fino alla versione 10gR1, le informazioni statistiche di uno statement non vengono aggiornate finché questo non si è concluso (iv). O meglio, la sessione aggiorna le statistiche di session e statement alla fine di ogni "database call" (v). Questo vuol dire che la macchina potrebbe star soffrendo a causa di latch contention, ma il nostro snapshot e relativo report non lo segnalano. 10gR2, ha modificato questo comportamento (v), aggiornando le statistiche ogni 5 sec.

4. Statement fantasma
Se il sistema è particolarmente sotto carico, potrebbe succedere che uno statement venga espulso dalla SQL AREA. In questo caso non sarà presente nello snapshot e quindi nel report (commento in v) (vi)


(ii) THE SELF-MANAGING DATABASE
(v) Scoping
(vi) A problem with Statspack

domenica, settembre 23, 2007

1 giorno con Joze Senegacnik

Devo essere sincero. Joze Senegacnik mi era del tutto sconosciuto. Forse anche perché da quando seguo più lo sviluppo che l'esercizio, ho perso un pò di visione su quello che è la tematica che riguardante strettamente il DBA.

Cercando in rete però, mi sono reso conto che Senegacnik deve essere uno in gamba, vista la sua presenza su siti di un certo calibro (hotsos, oaktable). E se guardiamo le sue pubblicazioni (non ancora scaricabili), il quadro risulta completo.

Ero quindi molto curioso di partecipare al seminario, anche se mi chiedevo come in un solo giorno (il 13 Settembre 2007 a Milano) potesse parlare degli internals di Oracle.

Se confrontato con i seminari di Kyte e Lewis, quello di Senegacnik, è stato di tutt'altra pasta. Mentre i primi due hanno forinto tools e metodologie, quest'ultimo si è limitato a fare una panoramica delle strutture interne di Oracle. Del resto in 7 ore di corso, non poteva fare altrimenti.

Dal mio punto di vista, il seminario è stato un riassunto di quanto avevo studiato fino ad allora prorpio: gestione della buffer cache, degli undo etc. La cosa interessante che non avevo mai visto è stata la sua discussione su RAC.

C'è da dire comunque che tutto il materiale su cui si è basato è disponibile in rete sul sito di Julian Dyke, nella sezione Presentations. Consiglio gli interessati di leggersi attentamente i documenti che vi si trovano.

Ma vediamo gli argomenti del seminario:

  1. Buffer Cache
  2. RAC and Cache Fusion, RAC specific wait events
  3. SGA and Library Cache
  4. Undo and Redo
  5. SQL Work Area Memory Management (PGA)

Come dicevo, quanto detto durante il corso, lo si può trovare sul sito di Julian Dyke. Quello che mi è sembrato interreante sono le seguenti cose:

  1. Sia in una istanza stand alone che in RAC, esiste una sola versione "corretente" del blocco. Nel caso di RAC, però, ciò significa che se più sessioni eseguono un UPDATE sullo stesso blocco, questo deve girare tra le istanze.
  2. Ogni istanza è MASTER per un pool di blocchi. Questo vuol dire che se un'applicazione è connessa ad una istanza I1 che non è master per il blocco richierichiesto, allora i) l'istanza I1, chiederà chi è il master per quel blocco; 2) si farà inviare il blocco in questione; 3) fornirà al client che ne ha fatto chiesta, la versione consistente del blocco.
  3. Se un'istanza è lenta a rispondere, tipicamente perché le cpu sono sature, allora viene fatto lo shutdown dell'istanza stessa.



sabato, giugno 16, 2007

Le tre leggi

To be or not to be (a DBA), that is the question
- Amleto

Qualcuno potrebbe pensare che scomodare addirittura Shakespeare per essere o meno un DBA sia un po eccessivo. Eccentirco forse, ma eccessivo no. Vediamo il perché.

NON essere un DBA è facile. Conosco qualcuno che si spaccia come tale, ma è ben lontano dall'esserlo. Piuttosto, essere un DBA, ha a che fare con il carattere. Ma a questo ci arriveremo.

I DBA, esistono a diversi livelli:

  • Chi si occupa di Installazione, Configurazione e Monitoring dell'RDBMS
  • Chi si occupa di Backup & Recovery (quì intendo anche Replicazione, Standby DB, etc)
  • Chi si occupa di HA (RAC ad esempio)
  • Chi si occupa di Performance and Tuning
  • Chi supporta lo sviluppo (DBA Applicativo)

Ovviamente esistono anche altri livelli di esistenza, ma mi premeva far capire la complessità dell'universo DBA.

A tutto questo va aggiunto che un DBA deve conoscere:

  • il Sistema Operativo, per affrontare problematiche si installazione, performance, tuning, backup
  • SQL & PL/SQL, per poter fare interrogazioni mirate sul db sia per il tuining che per il monitoring. Senza tener conto del supporto che deve fornire in qui casi in cui il codice è scritto male
  • linguaggi di scripting come bash, perl e tcl/tk, per il monitoring ed il reporting
  • linguaggi di programmazione come C/C++ e Java, per affrontare problematiche di installazione, di configurazione, supporto allo sviluppo

non è detto che debba conoscere tutto e bene, ma il "conoscere" sicuramente aiuta.

Cosa fondamentale poi, è che il DBA deve saper ascoltare. Deve saper interpretare le esigenze degli utilizzatori del DB. Deve saper capire quali sono i limiti degli utenti e fornire ove necessario valide alternative. E' per questo, ad esempio, che risulta fondamentale la conoscenza dell'SQL e del PL/SQL.

Il DBA deve avere quindi del carattere per poter sapientemente argomentare pregi e difetti di una soluzione. Il DBA deve aver carattere nel saper riconoscere i propri limiti. Il DBA deve aver carattere nell'ammettere che altri ne sanno più di lui. E soprattutto il DBA deve aver carattere dimostrandosi umile.

Quindi: si può fare il DBA per necessità, lo si puòfare per prestigio o solo per lavoro. Ma soprattutto lo si può fare per passione. La differenza? La differenza è il risultato finale: chi lo fa per passione ha fame di informazioni ed è sempre alla ricerca di nuove sfide da superare.

Un DBA cerca di conoscere le strutture fisiche e logiche degli schemi dei database che gestisce e cerca di comprendere le applicazione che li utilizzano: indaga sui perché di eventuali problemi e fornisce, come detto, valide alternative. Badate bene che "valide alternative" non vuol dire creare un indice o lanciare le statistiche: ci sono già tools che fanno questo. Tom Kyte in un suo interessantissimo thread, spiega bene l'idea (riporto parte della discussione):

Tools apply a set of rule, heuristics (like the things I have in my head after doing it for 15 years)... I can look at a query, and a plan -- and with a KNOWLEDGE of the data (statistics to the software, even more knowledge to a human) -- I can generally "make the query better". Not always, but many times. That is the software does, it applies a series of rules to the queries and suggests (based on rules of thumb) enhancements to the schema or the query that would make it better. I've yet to see any software take a query though and say things like "well, if you remove that non-necessary outer join, use the analytic functions instead it'll run much faster". I see them say "add this index" sort of advice (very basic).

Ma non solo. Un DBA deve preoccuparsi anche e soprattutto della sicurezza dei dati. Spesso si tende a confondere tale termine. Credo che il modo giusto di vedere la cosa sia nel dire che "sicurezza" racchiude in se tre concetti distinti:

  • Protezione

  • Affidabilità

  • Disponibilità

La sola mancaza di protezione implica l'assenza delle componenti di affidabilità e disponibilità. Se il dato non è protetto allora possiamo essere certi che prima o poi le modifiche fatte alla base dati andranno perse perché non esiste nesun criterio di garanzia sulle operazioni svolte.

Supponiamo ad esempio di avere uno schema, acceduto dall'applicazione per inviare sms (l'appicazione di produzione), dallo sviluppo per fare i test, dall'esercizio per la manutenzione e dal monitoring per controllare eventuali problemi. In questo caso la probabilità che un danno accidentale si verifichi risulta proporzionale alla grandezza della base dati e dal numero di utilizzatori della stessa.

Che dire: un gran casino.

Ho allora immaginato 3 leggi a cui un DBA deve attenersi. 3 leggi che devono governare la vita di un DB. Un po come le 3 leggi della robotica di Asimov (prima Shakespeare, adesso Asimov: chi mi ferma più):

  • Prima Legge: Il DBA deve garantire la sicurezza dei dati. Deve cioè garantire che siano rispettati i vincoli di Protezione, Affidabilità e Disponibilità;
  • Seconda Legge: Ogni utilizzatore del db deve modellare la propria base dati secondo le esigenze di performance della sua applicazione, purché queste non contrastino con la Prima Legge;
  • Terza Legge: Il DBA deve fornire ogni tipo di supporto agli utilizzatori del database, deve raccogliere le loro esigenze e suggerire valide alternative purché venga rispettata la Seconda Legge;

Vorrei concludere citando Stéphane Faroult, autore di The Art of SQL, edito da O'Reilly. Il libro si rifà, come si evince dal titolo, all'Arte della Guerra di Sun Tzu (questa non ve l'aspettavate, vero?). Nell'introduzione del libro, Faroult scrive:

[...] I realized that the problem of teaching developers how to use database efficiently was similar to the problem of teaching officers how to conduct a war. You need knowledge, you need skills, and you need talent. Talent cannot be taught, but it can be nurtured.

Direi che questa frase calzi perfettamenteanche ai DBA, oltre che agli sviluppatori.


venerdì, giugno 01, 2007

Il Costo è Tempo?

Jonathan Lewis nel suo libro Cost-Based Oracle Fundamentals, nel Cap1 pagina 4 dice:

According to the CPU costing model:
Cost = (
#SRds * sreadtim +
#MRds * mreadtim +
#CPUCycles / cpuspeed
) / sreadtim

where

#SRDs - number of single block reads
#MRDs - number of multi block reads
#CPUCycles - number of CPU Cycles
sreadtim - single block read time
mreadtim - multi block read time
cpuspeed - CPU cycles per second

Translated, this says the following:

The cost is the time spent on single-block reads, plus the time spent on multiblock reads, plus the CPU time required, all divided by the time it takes to do a single-block read. Which means the cost is the total predicted execution time for the statement, expressed in units of the single-block read time.

L’affermazione che il “costo è il tempo” viene ribadito anche sul suo sito, dove aggiunge note al suo libro. La sezione “Cost is time (30th Dec 2005)”, termina infatti con: “Cost is Time – but the units are a bit funny”.

In realtà, come poi Lewis stesso ammette, le cose sono un pò diverse da come sembrano. In un thread del suo Blog infatti, si corregge con la seguente affermazione:

[…] I should have said “resource consumption” rather than cost […]

Di fatto, non possiamo utilizzare il costo di uno statement per dire se è buono o meno. Il motivo di tale affermazione è il risultato di un thread sul sito di Kyte che devo dire essere estremamente interessante.

Il mio personale consiglio è ovviamente di leggerlo. Qui riporto la risposta che Wolfgang Breitling in quel thread da ad una domanda fatta da un lettore:

To those who cling to the illusion that the "cost" of an explained sql is in any way related to the performance, read Tom's lips: "It is not".
The cost is used during the parse to pick one plan among all the ones considered (the one with the lowest "cost"). Once it has served that purpose and a plan is chosen, it is meaningless. In particular, it can NOT be compared to the cost of a another explain. If everything is the same between the two explain, the resulting plans and their costs will be the same. If they are not, then something is different and you can not compare the results anymore.
In pre-Oracle9, the "cost" is roughly equal to the estimated number of logical reads (db blocks needed to find the answer). That estimate of the number of blocks to be visited can be different from reality for a number of reasons, only a few of which could be considered bugs. A lot of the reasons for wrong estimates are due to data distribution and dependencies. That is what Tom refers to a human knowledge about the data which goes far beyond what the optimizer can discern from the statistics. For a presentation I am giving at the Hotsos Performance Symposium (IOUG wasn't interested) I have prepared testcases where the same query on tables with virtually identical statistics returns vastly different numbers of rows to show that it is impossible for the optimizer to come up with accurate estimates and therefore the best plan in all cases.

Cost and execution time are NOT related. There are plenty of examples that prove that they are not. The comparison of costs can only be made by the optimizer while it is parsing a sql and is evaluating different access paths. Once an access path is chosen it is invalid to compare its cost number to that of a different plan and draw any conclusion from it.
When parsing a sql the optimizer, in addition to using the gathered statistics - table as well as system in 9i - the optimizer has to make many assumptions about the data (uniform distribution for example in the absence of histogram data) and if the reality differs from the assumption the plan that came out with the lowest cost based on the assumptions can very well be far inferior to a plan that has a higher cost number (based on the assumptions) but is better suited to the reality and hence performs better. It is a rather far stretch to call the inability of the optimizer to accurately estimate certain characteristics of the data in the database, given limited information, a bug.

giovedì, febbraio 08, 2007

...e 2 giorni con Jonathan Lewis

Prima di qualsiasi commento, mi preme fare una precisazione. Per chi ha un "buon" grado conoscenza ed un "ottimo" livello di preparazione, i giorni 6 e 7 Febbraio non hanno rappresentato nulla di nuovo (se ricordo bene, il valore 7 a scuola era l'equivalente di discreto, poi c'era buono (8), ottimo (9) ed infine eccelente (10)).

Ho ritenuto doveroso tale precisazione per fugare il dubbio se questi due giorni fossero stati o meno utili. Se poi consideriamo il privilegio di aver potuto assistere dal vivo ad una lezione tenuta da Jonathan Lewis ( e farsi autografare il libro)....... :)

Bene. Il seminario ha coperto diversi argomenti, tutti legati all'ottimizzatore. La cosa interessante è che Lewis osserva il modo (Oracle) proprio dal punto di vista del CBO. In quest'ottica, allora gli argomenti trattati hanno tutti un filo conduttore:

Giorno1:
======

  1. Aritmetica di base del COSTO
  2. Meccanismi di JOIN
  3. Selettività ed HINTS
  4. Come e dove trovare i piani di esecuzione
  5. Come leggere i piani di esecuzione

Giorno2:
======

  1. Problemi con i piani di esecuzione
  2. Uso degli indici
  3. Mito degli indici
  4. Descrivere i dati

Le informazioni che ha dato sono state davvero tante ed il mio unico rammarico è di non essere andato lì già preparato: diciamo che se avessi letto e studiato il suo libro, probabilmente avrei non solo apprezzato di più il suo intervento, ma sarei riuscito a catturare tutti i suggerimenti durante le due giornate.

In effetti se proprio dovessi muovere una critica al seminario sarebbe quella di essere stato troppo breve se rapportato alla quantità di cose discusse. Come dire: troppo, in troppo poco tempo. Ci sono state infatti cose che non sono riuscito a capire appieno ed altre che mi sono del tutto sfuggite. Ad esempio, non sono riuscito a capire esattamente l'algoritmo di HASH JOIN, anche se ne ho carpito il senso, ma mi è completamente sfuggito il funzionamento del piano di esecuzione di tipo BITMAP.

Lasciando però da parte le cose che mi sono sfuggite (diciamo il 20%), i restanti argomenti li ho trovati davvero utili.

  • Non è vero ad esempio che l'ottimizzatore, nel caso in cui deve restituire meno del 5% delle righe, utilizza un indice. Ci sono diversi fattori che influenzano il CBO per la scelta del piano di esecuzione: il parametro DB_FILE_MULTIBLOCK_READ_COUNT, il CLUSTERING FACTOR (CF, da adesso in poi), i parametri OPTIMIZER_INDEX_COST_ADJ (OICA) e OPTIMIZER_INDEX_CACHING (OIC), ad esempio.
  • Kyte nei suoi libri indica il fattore di clustering come "grado di disordine di un indice". Lewis ha dato un'altra definizione: "rappresenta la qualità di un indice". Ha inoltre tenuto a precisare che, nel caso in cui il CF approccia al numero di righe, non vuol dire che sia sbagliato. Il fatto è che se cerchiamo valori singoli in una tabella, allora il CF non ha rilevanza: lo ha nel caso in cui, per accedere alla tabella, facciamo un FULL SCAN dell'indice.
  • Le statistiche di sistema (quelle raccolte con dbms_stats.gather_system_stats) misurano le performance di un sistema, visto che valutano la velocità di un processore (Mega operazioni al secondo), valutano la lettura media di una lettura singola e di una lettura multi-blocco. In ogni caso ha detto di fare attenzione ad i numeri che ne derivano. Il fatto è che talvolta le statistiche risultano falsate perché i venditori di hardware ottimizzano i loro sistemi per velocizzare l'accesso al disco rendendo ad esempio più veloce la lettura dalla cache (vedi EMC, ad esempio).
  • Le statistiche di sistema (quelle raccolte con dbms_stats.gather_system_stats) hanno introdotto un nuovo modo di calcolare il costo. In Oracle 8i, c'era solo l'I/O cost, mentre a partire da Oracle 9i, è stato introdotto il CPU cost. Prima di Oracle 9i, cioè, c'erano due presupposti sbagliati:
    1. L'ottimizzatore assumeva che tutte le letture avvenivano da disco
    2. Non venivano considerati i tempi di accesso dell'indice e di un FULL SCAN: una lettura singolo-blocco, cioè, pesava esattamente come una lettura multi-blocco
    Per tale motivo sono stati forniti i parametri OICA e OIC

E queste sono solo alcuni degli argomenti trattati. Immagginate 2 giorni pieni zeppi di cose da apprendere e soprattutto utili al fine di capire come l'ottimizzatore lavora e su come valutare l'impatto dei parametri messi a disposizione dall'RDBMS per far fare al CBO esattamente ciò che noi vogliamo.

Famiglia e lavoro permettendo, cercherò di pubblicare gli appunti che ho preso durante il seminario. La cosa come potete immaginare non è semplice visto che devo ripercorrere tutte le slide del corso e adattare quello che ho scritto con ciò che lui a detto. Cmq, ci proverò.

venerdì, gennaio 05, 2007

Heisenberg Uncertainty Principle

Dopo qualche anno (ormai quasi 7) che lavoro con Oracle, devo ammettere che lo studio di questo database è diventato soprattutto una passione. L'acquisto dei libri tecnici a partire dal 1999, è sempre stato mirato all'approfondimento di Oracle stesso. E non parlo solo di libri specifici (Backup & Recovery, Amministrazione, Performance and Tuning (sopratutto), PL/SQL), ma anche di Sistema Operativi (Unix like), File System e Programmazione C. Ormai ho perso il conto dei soldi spesi.

Ma si sà: gli hobby costano.

Tuttavia, non tutti condividono il mio stesso entusiasmo per Oracle. Qualche giorno fa ho scritto una email a colui che mi ha insegnato le basi di Oracle.

Il suo punto di vista è molto diverso: sostiene che Oracle non è l'unico database e sulla piazza si trovano db che costano meno e sono ugualmente funzionali. Sinceramente non saprei come dargli torto, ma credo che il primo amore non si scordi mai......

--- cut here ---

E’ vero che non conosco altri db se non Oracle, ma devi ammettere che le funzionalità implementate sono valide.

Potrei decantarti le lodi di questo database (la 10g inizia una nuova vita), ma so che saresti in grado di confutarne ogni caratteristica. Ti inoltro allora un
documento
(1). Non so se lo hai già visto o letto, ma data la sua particolarità credo sia importante sottolineare lo sforzo fatto degli ingegneri per la realizzazione del software.

Non voglio anticiparti nulla, ti dico solo che non è la prima volta che il principio di intederminazione di Heisenberg viene tirato in ballo. Non sono un’esperto, ma una mia idea me la sono fatta.

La prima volta che ho visto porsi il problema di come effettuare misure corrette per individuare problemi di performance è stato nel libro Optimizing Oracle Performance (libro davvero incredibile. Scritto da Cary Millsap e Jeff Holt ed edito da O’Reilly). In un piccolo riquadro spiegano come sia difficle effettuare misure precise anche in sistemi di calcolo come i computer.

Il fatto poi di dover utilizzare software di terze parti, comporta l’alterazione del database stesso, per cui molte delle misure potrebbero essere imprecise.

In questo senso Oracle 10g ha fatto un passo avanti. A mio avviso ha cambiato la filosofia di approccio all’analisi: l’osservatore non influenza più l’osservto, ma è l’osservabile stesso a fornire le proprie informazioni.

--- cut here ---

(1) Qui il pdf in formato slide.

martedì, dicembre 19, 2006

Bad execution plans (Cattivi piani di esecuzione)

Le cose dette durante il seminario, di Tom Kyte sono state davvero incredibili ed alcune mi hanno colpito più di altre. Ad esempio: "quando Oracle sbaglia a calcolare la cardinalità delle righe allora sceglie un piano di esecuzione sbagliato". Coinciso e chiaro. Ovviamente una simile affermazione ha stimolato la mia curiosità e la sete di conoscenza ha fatto il resto. Cercando in rete, ho trovato sul blog di Kyte stesso un commento all'Hotsos Symposium 2006. Qui ne riporto un estratto:

That last one was Wolfgang Breitling?s talk. I really enjoyed that one for the simple reason it is a method I follow myself. The crux of the matter is ? you have a query that should perform better, you know it can. But the optimizer has generated the wrong plan (you know it did). Rather than just hinting it and fixing that one, sole query ? you can try to figure out "why" (and hence fix an entire class of poorly performing queries in the process, instead of tuning by hand every single one). The premise: bad query plans result from incorrect cardinality estimates. If you want to "tune a query", look to the estimated cardinality values (explain plan or v$sql_plan) and compare them to the actuals (row source operation in a TKPROF report, v$sql_plan_statistics). His approach, one I share, is to do that and then try to come up with a way to "fix it" ? to get the optimizer to achieve the correct cardinality. It might be optimizer dynamic sampling, it might be setting/gathering more detailed statistics ? but it will fix not only that particular query but an entire class of queries that might suffer from the same issue. I really liked this one.

Da ciò possiamo trarre alcune interessanti ed utili informazioni:
  • Per tunare una query dobbiamo valutarne il piano di esecuzione e la cardinalità delle righe risultanti
Per farlo abbiamo a disposizione (a partire da Oracle 9i) due nuove viste: V$SQL_PLAN e V$SQL_PLAN_STATISTICS. Queste, contengono il piano di esecuzione e le relative statistiche dello statement quando è stato eseguito. E la cosa è molto importante. Infatti, quando affrontiamo problemi di tuning, non sappiamo in che modo l'ottimizzatore ha valutato una query nell'istante in cui l'ha eseguita. Utilizzando queste due viste di sistema invece possiamo valutare le scelte del CBO.
  • In linea di massima, per fissare una classe di query che soffrono di uno stesso problema è sufficiente raccogliere le statistiche.
Il collezionamento delle statistiche è cruciale: statistiche mancanti o vecchie confondono l'ottimizzatore e spesso portano alla scelta sbagliata del piano di esecuzione: occorre valutare ad esempio se è il caso o meno di utilizzare gli histogrammi affinché la cardinalità stimata sia la più corretta possibile.

A partire dalla versione 10, l'ottimizatore RBO è stato desupportato. Per taleo motivo, le statistiche vengono collezionate in automatico. Il parametro OPTIMIZER_DYNAMIC_SAMPLING influenza il modo in cui il CBO si comporta. Di seguito riporto i valori di tale parametro per le versioni a partire da Oracle 9iR1 (non esiste un corrispettivo per release precedenti), mentre consiglio il seguente link per maggiori informazioni.
OPTIMIZER_FEATURES_ENABLEOPTIMIZER_DYNAMIC_SAMPLING
>= 10.0.02
9.2.01
9.0.10

Relativamente all'ottimmzatore CBO, il mio suggerimento è per due siti: i loro autori sono dei veri eseperti in materia ed i loro documenti sono dei veri casi di studio.

Wolfgang Breitling
Gli articoli che ha scritto sono davvero interessanti. Uno di questi, A Look under the Hood of CBO: The 10053 Event, descrive come interpretare le decisioni del CBO.

Jonathan Lewis
A parte che l'intero sito è una miniera di informazioni su tutto ciò che riguarda Oracle, l'autore ha srcitto un libro, Cost Based Oracle: Fundamentals, incentrato tutto sul CBO.

martedì, novembre 21, 2006

2 giorni con Tom Kyte...

Credo fosse estate o giù di lì quando lessi che Tom Kyte sarebbe venuto a Roma per tenere il suo primo seminario in Italia. Ricordo che come un bambino, ero tutto emozionato all'idea di poter seguire personalmente l'autore di ben 3 libri incredibili (tutti acquistati ovviamente).

Dovevo assolutamente partecipare. Ed infatti mossi mari e monti per cercare di non mancare l'appuntamento. Come a scuola, seduto nell'ultima fila ero armato di auricolari per ascoltare la traduzione in italiano (già, purtroppo ho questa mancanza: l'inglese): non mi sono perso una sola parola di quanto il buon Tom ha detto.

Ma ovviamente dovevo fare qualcosa. Dovevo segnare quel giorno e così alla fine della seconda giornata ho fatto 3 domande.

* Domanda. Come capire se soffro di "Write Consistency" (un effetto collaterale della "lettura consistente" che Oracle mette a disposizione)?
* Risposta. Non esistono particolari tecniche che consentono di individuare se la nostra applicazione è sotto l'effeto del "Write Consistency". L'unico suggerimeto è quello di lanciare una prima volta lo statement dopo aver messo sotto trace la nostra sessione e leggere i corrispondenti valori di "query" e "current" dall'output del file prodotto. Lanciare quindi una seconda volta lo stesso statement e ricontrollare il file di trace prodotto. Se siamo nelle condizioni di "Write Consistency", allora vedremo il valore "current" molto maggiore rispetto al caso precedente. E dovremmo basarci solo sul valore di "current" e non quello di "query", perché i blocchi letti in modo consistente in questo contensto non fanno testo (di fatto possiamo dire che il 95% delle letture sul db avviene dagli undo segment)

* Domanda. La seconda invece è stata relativa ad una cosa che avevo letto sul libro "Effective Oracle by Design". Non so se ricordate, ma ad un certo punto Kyte dimostra che spostare il codice di un trigger in una stored procedure (meglio in un package ovviamente) porta ad un guadagno in performance. Non dice tuttavia il perché di questo miglioramento. Quale occasione migliore della sua stessa presenza per avere una risposta?
* Risposta. Ebbene, ciò che succede è che Oracle esegue il cache del codice PL/SQL delle stored procedure (e quindi dei package) ma non di quello dei trigger. Spostando quindi la logica fuori dal trigger, consentiamo al db di effettuare meno parsing, guadagnando quindi in performance. Questo spostamento del codice fuori dal trigger non sarà più necessario a partire dalla versione 11g in quanto Oracale effetuerà anche il caching del codice PL/SQL di un trigger.

* Domanda. Ed infine una cosa che dovevo assolutamente sapere: quando uscirà il suo prossimo libro.
* Risposta. Purtroppo sembra che non lo abbia ancora finito di scrivere. Ci tocca quindi aspettare.

Ma non basta. Mi sono fatto firmare anche gli ultimi due libri (se riuscivo a trovare quello su 8i, mi sarei fatto autografare anche quello) che aveva scritto.

Insomma un evento eccezionale a cui non potevo assolutissimamente mancare. Che figata. Pensate, da anni seguo ciò che scrive sul suo sito e leggo gli aricoli che scrive su Oracle Magazine ed adesso addirittura ho seguito un suo seminario.

Wow.

Un commento sul corso. La struttura è stata di tipo standard:

Giorno 1
========
1. The Tools I Use
2. All About Binds
3. SQL Techniques
4. Read and Write Consistency

Giorno 2
========
1. Effective Schema
2. 10gR1
3. 10gR2

Come già detto è stato molto bello e direi anche emozionante (almeno per me). La seconda giornata però, mi duole ammetterlo, ha disatteso le mie aspettative. Si è parlato fondamentalmente delle nuove caratteristiche della 10g: utile sicuramente, ma un corso di "New Features" lo possono sostenere tutti. Lui, Tom, poteva puntare in alto anche il secondo giorno ed invece si è limitato a descriverci cosa è stato introdotto nell'ultima release del db e come sfruttare tale caratteristiche.

...e adesso posso dire....io c'ero!!!!! Il prossimo appuntamento, se ci riesco, è il 6-7 Febbraio 2006 a Milano per ascoltare e seguire un'altro mostro sacro: Jonathan Lewis. Quì il link dell'agenda.

Il materiale, slide e codice di esempio, lo si trova sul suo sito nella sezione "Files": il titolo è Denmark_Italy.zip. Spero presto di scrivere presto un resoconto di queste due indimenticabili ed incredibili giornate sul mio sito web.