Wednesday, October 28, 2009

My Dogs Ringworm Is Not Healing

Change http port of Oracle XE EM - (XE: Changing the default http port)

Determine the current configuration settings on your Oracle XE. Accessed through SQLPLUS with SYSTEM user (or anyone else with DBA privileges):
 
C: \\ WINDOWS \\ system32> sqlplus system @ xe SQL * Plus

: Release 10.1.0.2.0 - Production on Mi Jan 25 November : 44:33 2006

Copyright (c) 1982, 2004, Oracle. All rights reserved.

Enter password: Connected to

:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Beta SQL

> -
get current status SQL> select dbms_xdb.gethttpport as "HTTP-Port"
, dbms_xdb. getftpport as "FTP-Port" from dual;

HTTP-Port FTP-Port
---------- ---------- 8080 0


You can change the HTTP port and the port of FTP when you want only have a few precautions such as
  • Note that you need special privileges for <1024>
  • ports should check the ports used ( netstat -ano )
  • httpport the parameter defines the port that will run the MS.

 
SQL> - set port http and ftp port
SQL> begin 2
dbms_xdb.sethttpport ('80 '); - The value 80 is the new parameter
3 dbms_xdb.setftpport ( '2100 ') ; - The value 80 is the new parameter
4 end;
5 /

PL / SQL procedure successfully completed.

SQL> select dbms_xdb.gethttpport as "HTTP-Port"
, dbms_xdb.getftpport as "FTP-Port" from dual;

HTTP-Port FTP-Port
---------- --- 80 2100 -------


If you only want to use the database without allowing access through HTTP or FTP, you can disable these options as follows:

 
SQL> - disable http and ftp access
SQL> begin 2 dbms_xdb.sethttpport
('0 ');
3 dbms_xdb.setftpport ('0');
4 end;
5 /

PL / SQL procedure successfully completed.

SQL> -
get current status SQL> select dbms_xdb.gethttpport as "HTTP-Port"
, dbms_xdb.getftpport as "FTP-Port" from dual;

HTTP-Port FTP-Port
----- ----- ---------- 0 0

Tuesday, October 27, 2009

Uncontrollable Bladder What To Do

BULK COLLECT with thousands of records and the LIMIT clause


I see many times that when using BULK COLLECT in PL / SQL code, not put the LIMIT clause. When we do not use this clause, all you win is to ruin the memory of the process.
The LIMIT clause allows us to define the amount of 'data' which we will place in memory. When use LIMIT, the ideal is to define a value between 100 to 500. Personally, I choose the value 100 because in my experience is usually the best value. But because I choose a value so small and not 1000 or 5000 for example? Well, for the simple reason that handle large amounts of data in memory is more expensive to handle small quantities.
If you choose a high value on the edge, can be 3 cases:
- that your code will run faster (unlikely).
- that your code will run in the same time (unlikely).
- that your code will run slower (likely).

An example to better understand the consequences of not using the LIMIT clause.

TEST First, create a table with 10,000 records (to see the difference in the use of the LIMIT clause, you do not run the example with millions of records. With thousands of records about us enough to understand the issue) and a table with TEST_2 TEST table structure but no records:
 
SQL_9iR2> CREATE TABLE test AS SELECT level
2 id, 'oracle_' not being used in my current session in order to see clearly the difference in the statistics taken in each run.

<= 10000 ;
SQL_9iR2> exec dbms_session.FREE_UNUSED_USER_MEMORY;

PL / SQL procedure successfully completed.


execute a PL / SQL Bulk Collect but WITHOUT LIMIT clause:


SQL_9iR2> DECLARE 2 TYPE t_array_number
IS TABLE OF NUMBER;
3 t_array_varchar2 TYPE IS TABLE OF VARCHAR2 (50);
4 t_array_id t_array_number; 5 t_array_texto
t_array_varchar2;
 6 7 
CURSOR cur IS SELECT * FROM test;

8 BEGIN 9 OPEN cur;
10 LOOP 12 FETCH
11
cur BULK COLLECT INTO t_array_id, t_array_texto;
 13 14 FORALL i IN 1 .. INSERT INTO 
t_array_id.COUNT test_2
15 16 VALUES (t_array_id (i) t_array_texto (i));
17
18 EXIT WHEN cur% NOTFOUND;

19 20 END LOOP;
21 COMMIT;
22 CLOSE cur;
23 END;
24 /

PL / SQL procedure successfully completed.

Elapsed: 00:00:00.04


Before running the second code, I will release the memory again and not being used in my current session.


SQL_9iR2> exec dbms_session.FREE_UNUSED_USER_MEMORY ;

PL / SQL procedure successfully completed.


Now run the same code PL / SQL Bulk Collect with LIMIT clause but WITH:


SQL_9iR2> DECLARE 2 TYPE t_array_number
IS TABLE OF NUMBER;
3 t_array_varchar2 TYPE IS TABLE OF VARCHAR2 (50);
4 t_array_id t_array_number;
5 t_array_texto t_array_varchar2;
 6 7 
CURSOR cur IS SELECT * FROM test;

8 BEGIN 9 OPEN cur;
11 10 LOOP 12 FETCH
cur BULK COLLECT INTO t_array_id, t_array_texto
 LIMIT 100; 
13
14 FORALL i IN 1 .. INSERT INTO
t_array_id.COUNT 15 test_2
16 VALUES (t_array_id (i) t_array_texto (i));
17
18 EXIT WHEN cur% NOTFOUND;

19 20 END LOOP;
21 COMMIT;
22 CLOSE cur;
23 END;
24 / PL / SQL procedure successfully completed.

Elapsed: 00:00:00.04


We see that in the second run, I'm loading into memory on each fetch 100 records that I do. Unlike the first implementation, which loads all the data at once. Let

statistics from the previous 2 versions:


Name Ejecución_1 Ejecución_2
Difference ------------------------------ ----------- ----------- -----------
LATCH.kwqit: protect wakeup ti 1 0 -1
LATCH.simulator lru latch 1 0 -1
LATCH.spilled msgs queues list 1 0 -1
LATCH.transaction allocation 3 0 -3
LATCH.session timer 5 0 -5
LATCH.multiblock read objects 8 0 -8
LATCH.channel operations paren 11 0 -11
LATCH.child cursor hash table 20 8 -12
LATCH.Consistent RBA 56 6 -50
LATCH.lgwr LWN SCN 56 6 -50
LATCH.mostly latch-free SCN 56 6 -50
 LATCH.active checkpoint queue           63           7         -56 
LATCH.session idle bit 183 45 -138
LATCH.enqueues 219 49 -170
LATCH.redo writing 241 25 -216
LATCH.SQL memory manager worka 337 0 -337
LATCH.messages 427 42 -385
LATCH.simulator hash latch 844 4 -840
LATCH.dml lock allocation 1,428 154 -1,274
LATCH.shared pool 1,586 271 -1,315
LATCH.row cache enqueue latch 1,648 194 -1,454
LATCH.cache buffers lru chain 1,521 5 -1,516
LATCH.library cache pin alloca 2,900 362 -2,538
LATCH.row cache objects 4,438 502 -3,936
LATCH.enqueue hash chains 4,841 508 -4,333
LATCH.checkpoint queue latch 6,296 521 -5,775
LATCH.session allocation 19,333 1,893 -17,440
LATCH.undo global data 30,208 2,945 -27,263
LATCH.redo allocation 30,716 3,231 -27,485
LATCH.sequence cache 42,506 4,124 -38,382
LATCH.library cache pin -54.339 60.580 6.241 76.555 7.911
LATCH.library cache -68.644

Latch:


Ejecución_1 Ejecución_2 Percentage Difference
670.187 67.521 -602.666 992.56%



One of the things that interests me show you about these executions are LATCH (loquee). Although the implementation of the 2 PL / SQL code delayed to run the exact same thing (in this example, processing only 10,000 records), statistics show us that we lock for many more employees in the first execution in the second. But why does this happen? Recall that in the second run, all that changed in the code was the addition of the LIMIT clause. Well, as we said at the start, manage large amount of memory is more costly to handle short supply, so Oracle has to use much to handle loquee we climbed to 10,000 records in the first implementation report, which handle only 100 records in the second run.
This example is conducted with a concurrent user only .... but imagine what would happen if we have many concurrent users doing the same thing we ... and therefore, generating lots of loquee ....

NOTE: We must avoid at all costs and lock for that los loqueos afectan la performance del sistema. Mientras mayor sea la cantidad de loqueos, nuestro sistema se vuelve cada vez menos escalable; y como consecuencia, cada vez soporta menor cantidad de usuarios concurrentes.



How Do I Know If I Am A Will Beneficiary

Partitioned Tables - Command 'EXCHANGE'








Exchange Partition
En resumen, lo que hace la sentencia Exchange Partition es modificar el diccionario de datos y simular que los datos que ya tenemos cargados en una tabla, corresponden a una partición determinada de otra table.
Here is a simple example to better understand this topic:

SQL_10gR2> CREATE TABLE AS
data_1 level 2 SELECT id, timestamp'2000-11-02 9:00:00 'date

3 FROM dual 4 CONNECT BY
level data_2 CREATE TABLE AS SELECT level 2 id, timestamp'2001-9-10 13:00:00 'date 3 FROM dual 4 CONNECT BY level


What we did was create 2 tables with different dates in each of them.

Now create only the structure of the partitioned table where we will load the data:
 
SQL_10gR2> CREATE TABLE test
2 (id, date) PARTITION BY RANGE
3 (date)
4 (5 <= 100000 ; Table created. Elapsed: 00:00:01.06 SQL_10gR2> year_2000 PARTITION VALUES LESS THAN (timestamp'2000-12-02 00:00:00 '),
6 year_2001 PARTITION VALUES LESS THAN (timestamp'2001-10-10 00:00:00')
7)
<= 100000 ; Table created.
8 AS 9 SELECT 1, timestamp'2000-11-02 9:00:00 '

11 10 FROM dual WHERE 1 = 0;

 We will make an alter to change the data dictionary and relate each of the 2 tables with the respective partition create table TEST ... 


SQL_10gR2> ALTER TABLE test 2


year_2000
EXCHANGE PARTITION 3 with table 4
data_1

WITHOUT VALIDATION;

Table altered.


Elapsed: 00:00:00.03
  

SQL_10gR2> ALTER TABLE test 2 EXCHANGE PARTITION
year_2001
3 WITH table datos_2 4 WITHOUT VALIDATION
;

Table altered.
Elapsed: 00:00:00.02


SQL_10gR2> SELECT count(*) 2 FROM test ;
COUNT(*)
---------- 200000
1 row selected.

SQL_10gR2> SELECT count(*)
2 FROM datos_1 ; COUNT(*)
----------
0

1 row selected.

SQL_10gR2> SELECT count(*)
2 FROM datos_2 ;

COUNT(*)

0

---------- 1 row selected.


As we can see with Partition Exchange does not take us almost nothing to load the data into the partitioned table because we're not loading the data, simply adjust the data dictionary.

may notice that I added the sentence WITHOUT VALIDATION. What is this? WITHOUT VALIDATION usually a fast operation because it only modifies the data dictionary. If the partitioned table or placed in the Exchange Partition has a primary key or unique constraint enabled, then the Partition Exchange VALIDATION WITH done as to maintain the integrity of the constraints. Let

rerun the 2 previous alter without judging WITHOUT VALIDATION ...


SQL_10gR2> ALTER TABLE test 2


year_2000
EXCHANGE PARTITION 3 with table data_1;
Table altered.


Elapsed: 00:00:01.00


SQL_10gR2> ALTER TABLE test 2
 

year_2001 EXCHANGE PARTITION 3 with table data_2;
Table altered.


Elapsed: 00:00:01.05

If I run these alter with Trace, the Trace report I show, among other rulings, the following ...

select 1 from
"data_1" where TBL$OR$IDX$PART$NUM("TEST", 0, 3,1048576,"FECHA") != :1

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 1 0 0 Fetch 1 0.04 0.04 0 65 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------

total 3 0.04 0.04 0 66 0 0
  
Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 81 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
0 TABLE ACCESS FULL DATOS_1 (cr=65 pr=0 pw=0 time=44582 us)


select 1 from "DATOS_2" where TBL$OR$IDX$PART$NUM("TEST", 0, 3,1048576,"FECHA") != :1

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 1 0 0
Fetch 1 0.04 0.04 0 65 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------

total 3 0.04 0.04 0 66 0 0


Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 81 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
0 TABLE ACCESS FULL DATOS_2 (cr=65 pr=0 pw=0 time=46957 us)


Antes que nothing, we note that the alternative is implemented in more time, right? From the consultations we observed the Trace, we see that it is conducting a FULL SCAN of the tables and that is running a function in the WHERE of each query. Imagine if we have to make this kind of processes in environments with large volumes of data and wherein the system is saturated by the I / O to disk. What happens if we do not have the data separated by year in different tables, and instead have all the data in one table? Well, as exemplified by the table TEST just to load, could do the following ...


SQL_10gR2> CREATE TABLE test_2
2 (id, date)
3 PARTITION BY RANGE ( fecha )
4 (
5 PARTITION year_2000 VALUES LESS THAN ( timestamp'2000-12-02 00:00:00' ),
6 PARTITION year_2001 VALUES LESS THAN ( timestamp'2001-10-10 00:00:00' )
7 )
8 AS
9 SELECT *
10 FROM test ;

Table created.
 Elapsed: 00:00:05.04 

SQL_10gR2> DROP TABLE test ;

Table dropped.

SQL_10gR2> ALTER TABLE test_2 RENAME TO test ;

Table altered.

SQL_10gR2> SELECT count(*)
2 FROM test ;

COUNT(*)
----------
200000

1 row selected.