Oracle report with long running SQL - oracle

I have a report generate using Oracle Report Builder. The report has 82 SQL queries. Almost every queries perform heavy calculation. I'm doing financial report that has double entry for accounting. Sometimes, when I generate the report, the entries is not tally. And sometimes it's good. It looks like it's not doing it in "transactional way". Because it seems the data is keep running while generating the report.
I'm curious how the report execute the SQL query? Is it one by one or the whole report? How can I debug or see what query is executing?

Try using below query to check the active SQl running
select S.USERNAME, s.sid, s.osuser, t.sql_id, sql_text
from v$sqltext_with_newlines t,V$SESSION s
where t.address =s.sql_address
and t.hash_value = s.sql_hash_value
and s.status = 'ACTIVE'
and s.username <> 'SYSTEM'
order by s.sid,t.piece

Oracle Reports will issue your 82 different queries, as needed, according to the relationships between them in your Oracle Reports data model.
By default, in Oracle, you only get read consistency within a single SQL statement -- and that is your problem.
For example, suppose you have query Q_ACCOUNTS, which lists your chart of accounts, and query Q_JOURNAL_ENTRIES, which summarizes the journal entries made to a given account. In your Oracle Reports data model, suppose Q_JOURNAL_ENTRIES is linked to Q_ACCOUNTS.
In this case, Oracle reports will run Q_ACCOUNTS and then run Q_JOURNAL_ENTRIES once for each account. And here is the key point: there is no read consistency between the multiple executions of Q_JOURNAL_ENTRIES (nor is there consistence with Q_ACCOUNTS, for that matter).
So, if an accounting entry is made to debit account A and credit account B, and that entry is made after Q_JOURNAL_ENTRIES has run for A and before it has run for B, your report will only include the credit to B. And, so, your report will not add up.
I have never done it, but you might try to run a SET TRANSACTION READ ONLY SQL command in your "Before Report" trigger. This can give you transaction-level read consistency, which is what you need, but it comes with limitations (mainly, you cannot perform any database writes, as the name implies).

maybe you could try the "longops"
SELECT s.sid,
s.serial#,
sl.target, sl.OPNAME, sl.SQL_PLAN_OPERATION as OPERATION, sl.SQL_PLAN_OPTIONS as options,
ROUND(sl.elapsed_seconds/60) || ':' || MOD(sl.elapsed_seconds,60) elapsed,
ROUND(sl.time_remaining/60) || ':' || MOD(sl.time_remaining,60) remaining,
ROUND(sl.sofar/decode(sl.totalwork,0, decode(sl.sofar, 0,1), sl.totalwork )*100, 2) progress_pct, s.INST_ID , s.machine
FROM gv$session s,
v$session_longops sl
WHERE s.sid = sl.sid
AND s.serial# = sl.serial#(+)
and sl.elapsed_seconds(+) <> 0
ORDER BY ROUND(sl.sofar/decode(sl.totalwork,0, decode(sl.sofar, 0,1), sl.totalwork )*100, 2)

Related

What does Oracle use "select 1 from sys.obj$ where 1=0" for?

I was in our Oracle DB and saw this in the messages.
select 1 from sys.obj$ where 1=0;
I'm curious as to what it does. Is it just a session being initiated, a check to see if there is a sign of life?
That query is automatically generated by Oracle SQL Developer, it's nothing nefarious.
I can't tell exactly what the query is used for. But when I looked for it on a few hundred of our databases I found about 20 rows for completely unrelated users and databases. The only thing they had in common was the MODULE was set to "SQL Developer".
select executions, parsing_schema_name, module, first_load_time
from gv$sql
where sql_text = 'select 1 from sys.obj$ where 1=0';
Further queries on GV$SQL and DBA_AUDIT_TRAIL show other boring data dictionary queries being run at the same time. Which leads me to believe it's one of a set of background queries run for some Oracle SQL Developer feature.
select executions, parsing_schema_name, first_load_time, gv$sql.*
from gv$sql
where parsing_schema_name = '<user from above>'
order by gv$sql.first_load_time desc;

Oracle performance drop in massive table copy

Situation:
I'm using Oracle 11g R2 to work on two database users.
User U0 = original database with hundreds of tables
User U1 = copy of U0 to be used for simulating U0
To maintain U1, I run a script as below on U1 when simulation starts.
truncate table T1;
truncate table T2;
...
insert into T1 (select * from U0.T1)
insert into T2 (select * from U0.T2)
...
Problem: It had no problem for few days, but got slower after weeks.
Also it sometimes stop inserting records in tables, and in this case it always stops at same table. However I don't think that the table size is the problem since it has less than 20,000 records only.
I guess that this is due to resource problem in DBMS side, disk or memory, but have no idea how to resolve it. I could find a similar question as below without exact procedure to work around storage problem. Maybe this can be simple one to DBAs but unfortunately I'm not qualified for that.
Oracle performance issue with massive inserts and truncates (AWR attached)
Edit: following Jon Heller's comment, I've got query results as follows.
dba_resumable : no records.
gv$sql : 5~6 records queried but insert statement is not included.
Most notable one is "select TIME_WAITED_MICRO from V$SYSTEM_EVENT where event = 'Shared IO Pool Memory'". I guess it is due to insufficient memory.
report_sql_monitor : every sql_id returns "SQL Monitoring Report" without additional information.
Edit2: Please forget about edit above. Insert statement appeared in gv$sql query and SQL monitor result is as attached picture.
Edit3: This time SQL monitor returned Activity detail for the same insert statement.

How to recreate SAP queries in Oracle?

I need to recreate some SAP stored procedures in Oracle. I've been trying to find tutorials, similar questions, examples, etc about this but apparently no one had to do this before
What Oracle SQL query can be similar to this SAP query ?
SELECT * FROM A
INTO CORRESPONDING FIELDS OF TABLE B
FOR ALL ENTRIES IN C
WHERE a = C-a
AND x = y.
LOOP AT B INTO D.
D-b = E-b.
INSERT c FROM D.
IF SY-SUBRC <> 0.
WRITE: / 'error on insert', D-b, D-a.
ENDIF.
Any help will be appreciated, Thanks.
I recommend you to use transaction 'ST05' to trace your program. This tool will show details of the queries on the database including the exact SQL executed.
EDIT:
As a demonstration of the queries generated by SAP for Oracle let's execute this code and trace it with transaction 'ST05'. Remember to run 'ST05' before executing the program.
tables: mara.
data: it_mara type standard table of mara,
it_eina type standard table of eina.
select-options so_matnr for mara-matnr.
start-of-selection.
select matnr from mara into corresponding fields of table it_mara
up to 100 rows where matnr in so_matnr.
check sy-subrc eq 0.
select * from eina into table it_eina for all entries in it_mara
where matnr eq it_mara-matnr.
After execution check the output in transaction 'ST05':
If you want more details select an SQL statement in the screen and then click the button 'Explain'. You will see the following:
For better reference on transaction 'ST05' check this link.
Hope it helps.
The FOR ALL ENTRIES statement usually produces many queries which results are then grouped by UNION or UNION ALL.
Here is a really nice analysis for Microsoft SQL Server.
Because of the fact that UNION and UNION ALL are part of SQL standard I think it is implemented exactly the same for any other SQL database.
[EDIT]
As Mr Miranda stated it looks differently when it comes to Oracle database. I googled a bit and found this article where it is said that IN-LISTs are used which seems also to be plausible.

Oracle - Can't Find Long Running Queries

What am I missing here? I am trying to test identifying long running queries.
I have a test table with about 400 million rows called mytest.
I ran select * from mytest in sqlplus
In another window, I ran the script below to see my long running query
select s.username, s.sid, s.serial#, s.schemaname,
s.program, s.osuser, s.status, s.last_call_et
from v$session s
where last_call_et >= 1 – this is just for testing
My long running query does not show up in the result from the query above. If I change the criteria to be >=0, then I see my query showing the status as INACTIVE and last_call_et of 0 despite the fact that the query is still running. What can I do to see my long running queries like the select * from... above so that I can kill it?
Thanks
First, you need to understand what a query like select * from mytest is really doing under the covers because that's generally not going to be a long-running query. Oracle doesn't ever need to materialize that result set and isn't going to read all the data as the result of a single call. Instead, what goes on is a series of calls each of which cause Oracle to do a little bit of work. The conversation goes something like this.
Client: Hey Oracle, run the query for me: select * from mytest
Oracle: Sure thing (last_call_et resets to 0 to reflect that a new call started). I've generated a query plan and opened a cursor,
here's a handle (note that no work has been done yet to actually
execute the query)
Client: Cool, thanks. Using this cursor handle,
fetch me the next 50 rows (the fetch size is a client-side setting)
Oracle: Will do (last_call_et resets to 0 to reflect that a new call started). I started full scanning the table, read a couple of
blocks, and got 50 rows. Here you go.
Client: OK, I've processed
those. Using this cursor handle, fetch the next 50 rows
Repeat until all the data is fetched
At no point in this process is Oracle ever really being asked to do more than read a handful of blocks to get the 50 rows (or whatever the fetch size the client is requesting). At any point, the client could simply not request the next batch of data so Oracle doesn't need to do anything long-running. Oracle doesn't track the application think time between requests for more data-- it has no idea whether the client is a GUI that is in a tight loop fetching data or whether it is displaying a result to a human and waiting for a human to hit the "next" button. The vast majority of the time, the session is going to be INACTIVE because it's mostly waiting for the client to request the next batch of data (which it generally won't do until it had formatted the last batch of data for display and done the work to display it).
When most people talk about a long-running query, they're talking about a query that Oracle is actively processing for a relatively long time with no waits on a client to fetch the data.
You can use the below script to find long running query:
select * from
(
select
opname,
start_time,
target,
sofar,
totalwork,
units,
elapsed_seconds,
message
from
v$session_longops
order by start_time desc
)
where rownum <=1;

How do I show running processes in Oracle DB?

Is it possible to show other processes in progress on an Oracle database? Something like Sybases sp_who
I suspect you would just want to grab a few columns from V$SESSION and the SQL statement from V$SQL. Assuming you want to exclude the background processes that Oracle itself is running
SELECT sess.process, sess.status, sess.username, sess.schemaname, sql.sql_text
FROM v$session sess,
v$sql sql
WHERE sql.sql_id(+) = sess.sql_id
AND sess.type = 'USER'
The outer join is to handle those sessions that aren't currently active, assuming you want those. You could also get the sql_fulltext column from V$SQL which will have the full SQL statement rather than the first 1000 characters, but that is a CLOB and so likely a bit more complicated to deal with.
Realistically, you probably want to look at everything that is available in V$SESSION because it's likely that you can get a lot more information than SP_WHO provides.
After looking at sp_who, Oracle does not have that ability per se. Oracle has at least 8 processes running which run the db. Like RMON etc.
You can ask the DB which queries are running as that just a table query. Look at the V$ tables.
Quick Example:
SELECT sid,
opname,
sofar,
totalwork,
units,
elapsed_seconds,
time_remaining
FROM v$session_longops
WHERE sofar != totalwork;
This one shows SQL that is currently "ACTIVE":-
select S.USERNAME, s.sid, s.osuser, t.sql_id, sql_text
from v$sqltext_with_newlines t,V$SESSION s
where t.address =s.sql_address
and t.hash_value = s.sql_hash_value
and s.status = 'ACTIVE'
and s.username <> 'SYSTEM'
order by s.sid,t.piece
/
This shows locks. Sometimes things are going slow, but it's because it is blocked waiting for a lock:
select
object_name,
object_type,
session_id,
type, -- Type or system/user lock
lmode, -- lock mode in which session holds lock
request,
block,
ctime -- Time since current mode was granted
from
v$locked_object, all_objects, v$lock
where
v$locked_object.object_id = all_objects.object_id AND
v$lock.id1 = all_objects.object_id AND
v$lock.sid = v$locked_object.session_id
order by
session_id, ctime desc, object_name
/
This is a good one for finding long operations (e.g. full table scans). If it is because of lots of short operations, nothing will show up.
COLUMN percent FORMAT 999.99
SELECT sid, to_char(start_time,'hh24:mi:ss') stime,
message,( sofar/totalwork)* 100 percent
FROM v$session_longops
WHERE sofar/totalwork < 1
/
Keep in mind that there are processes on the database which may not currently support a session.
If you're interested in all processes you'll want to look to v$process (or gv$process on RAC)

Resources