Efficient Query...
Hi ppl if possible please give me a more efficient query which does the same job as follows.....
SELECT order_no order_no,
contract contract,
vendor_no vendor_no
FROM Purchase_Order_Tab p, Purchase_Order_Line_Tab pl
WHERE p.order_no = pl.order_no
AND order_no IN (SELECT DISTINCT(order_no)
FROM (SELECT order_no, line_no, release_no
FROM Purchase_Order_Line_Tab
MINUS
SELECT order_no, line_no, release_no
FROM Purchase_Order_Invoice_Tab))
Thx for ur concern.... :-)
Hi,
Try this:
SELECT order_no order_no,
contract contract,
vendor_no vendor_no
FROM Purchase_Order_Tab p, Purchase_Order_Line_Tab pl
WHERE p.order_no = pl.order_no
AND (pl.order_no, pl.line_no, pl.release_no)
NOT IN (SELECT order_no, line_no, release_no
FROM Purchase_Order_Invoice_Tab)
Note: You can use NOT EXIST also.
** NOT TESTED **
Regards
Similar Messages
-
Suggests for a more efficient query?
I have a client (customer) that uses a 3rd party software to display graphs of their systems. The clients are constantly asking me (the DBA consultant) to fix the database so it runs faster. I've done as much tuning as I can on the database side. It's now time to address the application issues. The good news is my client is the 4th largest customer of this 3rd party software and the software company has listened and responded in the past to suggestions.
All of the tables are setup the same with the first column being a DATE datatype and the remaining columns are values for different data points (data_col1, data_col2, etc.). Oh, that first date column is always named "timestamp" in LOWER case so got to use double quotes around that column name all of the time. Each table collects one record per minute per day per year. There are 4 database systems, about 150 tables per system, averaging 20 data columns per table. I did partition each table by month and added a local index on the "timestamp" column. That brought the full table scans down to full partition index scans.
All of the SELECT queries look like the following with changes in the column name, table name and date ranges. (Yes, we will be addressing the issue of incorporating bind variables for the dates with the software provider.)
Can anyone suggest a more efficient query? I've been trying some analytic function queries but haven't come up with the correct results yet.
SELECT "timestamp" AS "timestamp", "DATA_COL1" AS "DATA_COL1"
FROM "T_TABLE"
WHERE "timestamp" >=
(SELECT MIN("tb"."timestamp") AS "timestamp"
FROM (SELECT MAX("timestamp") AS "timestamp"
FROM "T_TABLE"
WHERE "timestamp" <
TO_DATE('2006-01-21 00:12:39', 'YYYY-MM-DD HH24:MI:SS')
UNION
SELECT MIN("timestamp")
FROM "T_TABLE"
WHERE "timestamp" >=
TO_DATE('2006-01-21 00:12:39', 'YYYY-MM-DD HH24:MI:SS')) "tb"
WHERE NOT "timestamp" IS NULL)
AND "timestamp" <=
(SELECT MAX("tb"."timestamp") AS "timestamp"
FROM (SELECT MIN("timestamp") AS "timestamp"
FROM "T_TABLE"
WHERE "timestamp" >
TO_DATE('2006-01-21 12:12:39', 'YYYY-MM-DD HH24:MI:SS')
UNION
SELECT MAX("timestamp")
FROM "T_TABLE"
WHERE "timestamp" <=
TO_DATE('2006-01-21 12:12:39', 'YYYY-MM-DD HH24:MI:SS')) "tb"
WHERE NOT "timestamp" IS NULL)
ORDER BY "timestamp"
Here are the queries for a sample table to test with:
CREATE TABLE T_TABLE
( "timestamp" DATE,
DATA_COL1 NUMBER
INSERT INTO T_TABLE
(SELECT TO_DATE('01/20/2006', 'MM/DD/YYYY') + (LEVEL-1) * 1/1440,
LEVEL * 0.1
FROM dual CONNECT BY 1=1
AND LEVEL <= (TO_DATE('01/25/2006','MM/DD/YYYY') - TO_DATE('01/20/2006', 'MM/DD/YYYY'))*1440)
Thanks.No need for analytic functions here (theyll likely be slower).
1. No need for UNION ... use UNION ALL.
2. No need for <quote>WHERE NOT "timestamp" IS NULL</quote> the MIN and MAX will take care of nulls.
3. Ask if they really need the data sorted the s/w with the graphs may do its own sorting
in which case take the ORDER BY out too.
4. Make sure to have indexes on "timestamp".
What you want to see for those innermost MAX/MIN subqueries are executions like:
03:19:12 session_148> SELECT MAX(ts) AS ts
03:19:14 2 FROM "T_TABLE"
03:19:14 3 WHERE ts < TO_DATE('2006-01-21 00:12:39', 'YYYY-MM-DD HH24:MI:SS');
TS
21-jan-2006 00:12:00
Execution Plan
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2.0013301108 Card=1 Bytes=9)
1 0 SORT (AGGREGATE)
2 1 FIRST ROW (Cost=2.0013301108 Card=1453 Bytes=13077)
3 2 INDEX (RANGE SCAN (MIN/MAX))OF 'T_IDX' (INDEX) (Cost=2.0013301108 Card=1453 Bytes=13077) -
Efficiently Querying Large Table
I have to query a recordset of 14k records against (join) a very large table: billions of data -even a count of the table does not return any resulty after 15 mins.
I tried a plsql procedure to store the first recordset in a temp table and then preparing two cursors: one on the temp table and the other on the large table.
However, the plsql procedure runs for a long time and just gives up with this error:
SQL> exec match;
ERROR:
ORA-01041: internal error. hostdef extension doesn't exist
BEGIN match; END;
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Is there is way through which I can query more efficiently?
- Using chucks of records from the large table at a time - how to do that? (rowid)
- Or just ask the dba to partition the table - but the whole table would still need to be queried.
The temp table is:
CREATE TABLE test AS SELECT a.mon_ord_no, a.mo_type_id, a.p2a_pbu_id, a.creation_date,b.status_date_time,
a.expiry_date, a.current_mo_status_desc_id, a.amount,
a.purchaser_name, a.recipent_name, a.mo_id_type_id,
a.mo_redeemed_by_id, a.recipient_type, c.pbu_id, c.txn_seq_no, c.txn_date_time
FROM mon_order a, mo_status b, host_txn_log c
where a.mon_ord_no = b.mon_ord_no
and a.mon_ord_no = c.mon_ord_no
and b.status_date_time = c.txn_date_time
and b.status_desc_id = 7
and a.current_mo_status_desc_id = 7
and a.amount is not null
and a.amount > 0
order by b.status_date_time;
and the PL/SQL Procedure is:
CREATE OR REPLACE PROCEDURE MATCH
IS
--DECLARE
deleted INTEGER :=0;
counter INTEGER :=0;
CURSOR v_table IS
SELECT DISTINCT pbu_id, txn_seq_no, create_date
FROM host_v
WHERE status = 4;
v_table_record v_table%ROWTYPE;
CURSOR temp_table (v_pbu_id NUMBER, v_txn_seq_no NUMBER, v_create_date DATE) IS
SELECT * FROM test
WHERE pbu_id = v_pbu_id
AND txn_seq_no = v_txn_seq_no
AND creation_date = v_create_date;
temp_table_record temp_table%ROWTYPE;
BEGIN
OPEN v_table;
LOOP
FETCH v_table INTO voucher_table_record;
EXIT WHEN v_table%NOTFOUND;
OPEN temp_table (v_table_record.pbu_id, v_table_record.txn_seq_no, v_table_record.create_date);
LOOP
FETCH temp_table INTO temp_table_record;
EXIT WHEN temp_table %FOUND;
DELETE FROM test WHERE pbu_id = v_table_record.pbu_id AND
temp_table_record.txn_seq_no = v_table_record.txn_seq_no AND
temp_table_record.creation_date = v_table_record.create_date;
END LOOP;
CLOSE temp_table;
END LOOP;
CLOSE v_table;
END MATCH;
/Many thanks,
I can get the explain plan for the SQL statement, but I am not sure how to get it for teh PLSQL. Which section in the PLSQL do I get the explain plan. I am using SQL Navigator.
I can create the cursor with the join, and if it does not need the delete statement, then there is no need requirement for the procedure itself. Should I just run the query as a SQL statement?
You have not said what I should do with the rowid?
Regards -
3 Table Joins -- Need a more efficient Query
I need a 3 table join but need to do it more efficiently than I am currently doing. The query is taking too long to execute (in excess of 20 mins. These are huge tables with 10 mil + records). Here is what the query looks like right now. I need 100 distinct acctnum from the below query with all the conditions as requirements.
THANKS IN ADVANCE FOR HELP!!!
SELECT /*+ parallel */
FROM (SELECT /*+ parallel */ DISTINCT (a.acctnum),
a.acctnum_status,
a.sys_creation_date,
a.sys_update_date,
c.comp_id,
c.comp_lbl_type,
a.account_sub_type
FROM account a
LEFT JOIN
company c
ON a.comp_id = c.comp_id AND c.comp_lbl_type = 'IND',
subaccount s
WHERE a.account_type = 'I'
AND a.account_status IN ('O', 'S')
and s.subaccount_status in ('A','S')
AND a.account_sub_type NOT IN ('G', 'V')
AND a.SYS_update_DATE <= SYSDATE - 4 / 24)
where ROWNUM <= 100 ;Hi,
Whenever you have a question, post CREATE TABLE and INSERT statements for a little sample data, and the results you want from that data. Explain how you get those results from that data.
Simplify the problem, if possible. If you need 100 distinct rows, post a problem where you only need, say, 3 distinct rows. Just explain that you really need 100, and you'll get a solution that works for either 3 or 100.
Always say which version of Oracle you're using (e.g. 11.2.0.3.0).
See the forum FAQ: https://forums.oracle.com/message/9362002
For tuning problems, also see https://forums.oracle.com/message/9362003
Are you sure the query you posted is even doing what you want? You're cross-joining s to the other tables, producing all possible combinations of rows, and then picking 100 of those in no particular order (not even random order). That's not necessarily wrong, but it certainly is suspicious.
If you're only interested in 100 rows, there's probably some way to write the query so that it picks 100 rows from the big tables first. -
Hi,
I need to write an efficient query because the query involves 4 checks to be performed on rows before returning a single row. Here is a sample query script for creating the table:
CREATE TABLE "myschema"."Complaint"
"Compalint_ID" NUMBER(20,0),
"ReplyTime" NUMBER, -- this would be in minutes
"CREATION_TIME" TIMESTAMP (6),
"STATUS" NUMBER,
"TYPE" NUMBER,
CONSTRAINT "CH_PKRTBL_Complaint_ID" PRIMARY KEY ("Compalint_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "myspace" ENABLE
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "myspace" ;
CREATE UNIQUE INDEX "myschema"."CH_PKRTBL_Complaint_ID" ON "myschema"."Complaint" ("Compalint_ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "myspace" ;
ALTER TABLE "myschema"."Complaint" ADD CONSTRAINT "CH_PKRTBL_TKTID" PRIMARY KEY ("Compalint_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "myspace" ENABLE;
I want to write an efficient sql/pl-sql query with least time to return a row based on following four checks/priorities in order spcified below:
1. Retun any row which has TYPE = 11
2. If no row found for 1st check then
calculate a time difference for all rows as: time_difference (CREATION_TIME - ReplyTime)
and return the row which has largest differene in -ve (that is the row which has expired first)
3. If now row found for check 2 then
return row where SATUS = 22
4. If no row found for check 3 then
calculate a time difference for all rows as: time_difference (CREATION_TIME - ReplyTime)
and return the row which has smallest differene in +ve (that is the row which is going to expire next)
Kindly help me in achieving this task.
Thanks.Just an idea (not sure about the definitions first expired and next to expire )
select complaint_id,reply_time,creation_time,complaint_status,complaint_type,
from (select complaint_id,reply_time,creation_time,complaint_status,complaint_type,
case complaint_type when 11 then 11 end check1,
systimestamp - (creation_time + reply_time / 60/24) check2,
case complaint_type when 22 then 22 end check3,
systimestamp - (creation_time + reply_time / 60/24) check4,
max(case complaint_type when 11 then 11 end) over
(order by null rows between unbounded preceding and unbounded following) check1_max,
min(case when systimestamp - (creation_time + reply_time / 60/24) < 0
then systimestamp - (creation_time + reply_time / 60/24)
end
) over
(order by null rows between unbounded preceding and unbounded following) check2_max,
max(case complaint_type when 22 then 22 end) over
(order by null rows between unbounded preceding and unbounded following) check3_max,
min(case when systimestamp - (creation_time + reply_time / 60/24) > 0
then systimestamp - (creation_time + reply_time / 60/24)
end
) over
(order by null rows between unbounded preceding and unbounded following) check4_min
from complaint
where coalesce(check1,check2,check3,check4) = coalesce(check1_max,check2_max,check3_max,check4_min)Regards
Etbin -
Help with query to determine if a record value has changed.
Our auditors want to know which items had their costs updated in March 2006. I'm querying the cst_standard_cost table to find records that were updated in March. This part seems to be working although it pulls back multiple rows for the same item if more than one update was done in that month. I'm still not sure how I'm going to handle that problem.
----cst_standard_costs-----
alter session set NLS_DATE_FORMAT = 'MM/DD/YYYY';
drop table suss.cost_update_0306b;
create table suss.cost_update_0306b
as
select csc.inventory_item_id, mtl.segment1||','||mtl.segment2 "item", csc.organization_id,csc.standard_cost,csc.creation_date "creation_date"
from cst_standard_costs csc, mtl_system_items_b mtl
where csc.inventory_item_id = mtl.inventory_item_id
and mtl.organization_id = '82'
and csc.organization_id not in ('0','81')
and csc.creation_date like '03/%/2006%'
order by csc.inventory_item_idHere, I'm trying to find if the update that was done in March actually changed the item's cost. But the sql is not exactly right. The results being returned are any cost update where the item's cost is different than it was in March. I'd like to pull back the item's cost from the most recent cost update previous to the March update and see if it differs from the March cost.
select csc.inventory_item_id,mtl.segment1||','||mtl.segment2, csc.organization_id,csc.standard_cost, csc.creation_date
from cst_standard_costs csc, mtl_system_items_b mtl, suss.cost_update_0306b scu
where csc.inventory_item_id = mtl.inventory_item_id
and mtl.organization_id = '82'
and scu.inventory_item_id = csc.inventory_item_id
and csc.organization_id not in ('0','81')
and csc.creation_date < scu."creation_date"
and csc.standard_cost <>scu.standard_cost
order by csc.inventory_item_id ascHere's a simple example
item id.....cost.........update_date
24..........45.00........03/01/2006
24..........45.00........02/01/2006
24..........30.00........02/22/2006
40..........45.00........03/01/2006
40..........30.00........02/01/2006
40..........28.00........02/22/2006
The results of the sql should be to return item id 40 because the costs changed in March but not item id 24 because the costs did not change in MarchSomething like this:
SQL> DESC COSTS;
Name Null? Type
ITEM_ID NUMBER
COST NUMBER(4,2)
UPDATE_DATE DATE
SQL> SELECT * FROM COSTS;
ITEM_ID COST UPDATE_DAT
24 40 03/01/2006
24 45 02/01/2006
40 45 03/01/2006
40 30 02/01/2006
SQL> SELECT b.item_id, b.cost, b.update_date
2 FROM costs a, costs b
3 WHERE a.item_id = b.item_id
4 AND a.cost <> b.cost
5 AND a.update_date = ADD_MONTHS(b.update_date, -1)
6 /
ITEM_ID COST UPDATE_DAT
24 40 03/01/2006
40 45 03/01/2006It is maybe not efficient query but works :)
Another solution:
1 SELECT a.item_id, a.cost, a.update_date
2 FROM costs a
3 WHERE a.cost <> (SELECT cost
4 FROM costs
5 WHERE a.item_id = item_id
6 AND ADD_MONTHS(a.update_date, -1) = update_date
7* )
SQL> /
ITEM_ID COST UPDATE_DAT
24 40 03/01/2006
40 45 03/01/2006Peter D. -
Delay when querying from CUBE_TABLE object, what is it?
Hi Guys,
We are using Oracle OLAP 11.2.0.2.0 with an 11g Cube, 7 Dimensions, Compressed and partitioned by Month.
We have run into a performance issue when implementing OBIEE.
The main issue we have is a delay while drilling on a hierarchy. Users have been waiting 7-12 seconds per drill on a hierarchy, and the query is only returning a few cells of data. We have managed to isolate this to slow performing queries on CUBE_TABLE.
For example, the following query returns one cell of data:
SELECT FINSTMNT_VIEW.BASE, FINSTMNT_VIEW.REPORT_TYPE, FINSTMNT_VIEW.COMPANY, FINSTMNT_VIEW.SCENARIO, FINSTMNT_VIEW.PRODUCT, FINSTMNT_VIEW.ACCOUNT, FINSTMNT_VIEW.SITE, FINSTMNT_VIEW.TIME
FROM "SCHEMA1".FINSTMNT_VIEW FINSTMNT_VIEW
WHERE
FINSTMNT_VIEW.REPORT_TYPE IN ('MTD' )
AND FINSTMNT_VIEW.COMPANY IN ('E01' )
AND FINSTMNT_VIEW.SCENARIO IN ('ACTUAL' )
AND FINSTMNT_VIEW.PRODUCT IN ('PT' )
AND FINSTMNT_VIEW.ACCOUNT IN ('APBIT' )
AND FINSTMNT_VIEW.SITE IN ('C010885' )
AND FINSTMNT_VIEW.TIME IN ('JUN11' ) ;
1 Row selected in 4.524 Seconds
Note: FINSTMNT_VIEW is the automatically generated cube view.
CREATE OR REPLACE FORCE VIEW "SCHEMA1"."FINSTMNT_VIEW" ("BASE","REPORT_TYPE", "COMPANY", "SCENARIO", "PRODUCT", "ACCOUNT", "SITE", "TIME")
AS
SELECT "BASE", "REPORT_TYPE", "COMPANY", "SCENARIO", "PRODUCT", "ACCOUNT", "SITE", "TIME"
FROM TABLE(CUBE_TABLE('"SCHEMA1"."FINSTMNT"') ) ;
If we increase the amount of data returned by adding to the query, it only increased the query time by .4 seconds
SELECT FINSTMNT_VIEW.BASE, FINSTMNT_VIEW.REPORT_TYPE, FINSTMNT_VIEW.COMPANY, FINSTMNT_VIEW.SCENARIO, FINSTMNT_VIEW.PRODUCT, FINSTMNT_VIEW.ACCOUNT, FINSTMNT_VIEW.SITE, FINSTMNT_VIEW.TIME
FROM "SCHEMA1".FINSTMNT_VIEW FINSTMNT_VIEW
WHERE
FINSTMNT_VIEW.REPORT_TYPE IN ('MTD' )
AND FINSTMNT_VIEW.COMPANY IN ('E01' )
AND FINSTMNT_VIEW.SCENARIO IN ('ACTUAL' )
AND FINSTMNT_VIEW.PRODUCT IN ('PT' )
AND FINSTMNT_VIEW.ACCOUNT IN ('APBIT' )
AND FINSTMNT_VIEW.SITE IN ('C010885', 'C010886', 'C010891', 'C010892', 'C010887', 'C010888', 'C010897', 'C010893', 'C010890', 'C010894', 'C010896', 'C010899' )
AND FINSTMNT_VIEW.TIME IN ('JUN11' ) ;
12 rows selected - In 4.977 Seconds
If we increase the data returned even more:
SELECT FINSTMNT_VIEW.BASE, FINSTMNT_VIEW.REPORT_TYPE, FINSTMNT_VIEW.COMPANY, FINSTMNT_VIEW.SCENARIO, FINSTMNT_VIEW.PRODUCT, FINSTMNT_VIEW.ACCOUNT, FINSTMNT_VIEW.SITE, FINSTMNT_VIEW.TIME
FROM "SCHEMA1".FINSTMNT_VIEW FINSTMNT_VIEW
WHERE
FINSTMNT_VIEW.REPORT_TYPE IN ('MTD' )
AND FINSTMNT_VIEW.COMPANY IN ('ET', 'E01', 'E02', 'E03', 'E04' )
AND FINSTMNT_VIEW.SCENARIO IN ('ACTUAL' )
AND FINSTMNT_VIEW.PRODUCT IN ('PT', 'P00' )
AND FINSTMNT_VIEW.ACCOUNT IN ('APBIT' )
AND FINSTMNT_VIEW.SITE IN ('C010885', 'C010886', 'C010891', 'C010892', 'C010887', 'C010888', 'C010897', 'C010893', 'C010890', 'C010894', 'C010896', 'C010899' )
AND FINSTMNT_VIEW.TIME IN ('JUN11', 'JUL11', 'AUG11', 'SEP11', 'OCT11', 'NOV11', 'DEC11', 'JAN12') ;
118 rows selected - In 14.213 Seconds
If we take the time for each query and divide by the number of rows, we can see that querying more data results in a much more efficient query:
Time/Rows returned:
1 Row - 4.524
12 Rows - 0.4147
118 Rows - 0.120449153
It seems like there is an initial delay of approx 4 seconds when querying the CUBE_TABLE object. Using AWM to query the same data using LIMIT and RPR is almost instantaneous...
Can anyone explain what this delay is, and if there is any way to optimise the query?
Could it be the AW getting attached before each query?
Big thanks to anyone that can help!Thanks Nasar,
I have run a number of queries with logging enabled, the things you mentioned all look good:
Loop Optimization: GDILoopOpt COMPLETED
Selection filter: FILTER_LIMITS_FAST 7
ROWS_FAILED_FILTER 0
ROWS_RETURNED 1
Predicates: 7 pruned out of 7 predicates
The longest action I have seen in the log is the PAGING operation... but I do not see this on all queries.
Time Total Time OPERATION
2.263 27.864 PAGING DYN_PAGEPOOL TRACE GREW 9926KB to 59577KB
1.825 25.601 PAGING DYN_PAGEPOOL TRACE GREW 8274KB to 49651KB
1.498 23.776 PAGING DYN_PAGEPOOL TRACE GREW 6895KB to 41377KB
1.232 22.278 PAGING DYN_PAGEPOOL TRACE GREW 5747KB to 34482KB
1.17 21.046 PAGING DYN_PAGEPOOL TRACE GREW 4788KB to 28735KB
1.03 19.876 PAGING DYN_PAGEPOOL TRACE GREW 3990KB to 23947KB
2.808 18.846 PAGING DYN_PAGEPOOL TRACE GREW 3325KB to 19957KB
What is strange is that the cube operation log does not account for all of the query time. For example:
SELECT "BASE_LVL" FROM TABLE(CUBE_TABLE('"EXAMPLE"."FINSTMNT"'))
WHERE
"RPT_TYPE" = 'MTD' AND
"ENTITY" = 'ET' AND
"SCENARIO" = 'ACTUAL' AND
"PRODUCT" = 'PT' AND
"GL_ACCOUNT" = 'APBIT' AND
"CENTRE" = 'TOTAL' AND
"TIME" = 'YR09';
This query returns in 6.006 seconds using SQL Developer, if I then take the CUBE_OPERATION_LOG for this query and subtract the start time from the end time, I only get 1.67 seconds. This leaves 4.3 seconds unaccounted for... This is the same with the my other queries, see actual time and logged time below:
Query Actual Logged Variance
S3 6.006 1.67 4.336
L1 18.128 13.776 4.352
S1 4.461 0.203 4.258
L2 4.696 0.39 4.306
S2 5.882 1.575 4.307
Any ideas on what this could be or how I can capture this 4.3 second overhead?
Your help has been greatly appreciated. -
How to measure the performance of sql query?
Hi Experts,
How to measure the performance, efficiency and cpu cost of a sql query?
What are all the measures available for an sql query?
How to identify i am writing optimal query?
I am using Oracle 9i...
It ll be useful for me to write efficient query....
Thanks & Regardspsram wrote:
Hi Experts,
How to measure the performance, efficiency and cpu cost of a sql query?
What are all the measures available for an sql query?
How to identify i am writing optimal query?
I am using Oracle 9i... You might want to start with a feature of SQL*Plus: The AUTOTRACE (TRACEONLY) option which executes your statement, fetches all records (if there is something to fetch) and shows you some basic statistics information, which include the number of logical I/Os performed, number of sorts etc.
This gives you an indication of the effectiveness of your statement, so that can check how many logical I/Os (and physical reads) had to be performed.
Note however that there are more things to consider, as you've already mentioned: The CPU bit is not included in these statistics, and the work performed by SQL workareas (e.g. by hash joins) is also credited only very limited (number of sorts), but e.g. it doesn't cover any writes to temporary segments due to sort or hash operations spilling to disk etc.
You can use the following approach to get a deeper understanding of the operations performed by each row source:
alter session set statistics_level=all;
alter session set timed_statistics = true;
select /* findme */ ... <your query here>
SELECT
SUBSTR(LPAD(' ',DEPTH - 1)||OPERATION||' '||OBJECT_NAME,1,40) OPERATION,
OBJECT_NAME,
CARDINALITY,
LAST_OUTPUT_ROWS,
LAST_CR_BUFFER_GETS,
LAST_DISK_READS,
LAST_DISK_WRITES,
FROM V$SQL_PLAN_STATISTICS_ALL P,
(SELECT *
FROM (SELECT *
FROM V$SQL
WHERE SQL_TEXT LIKE '%findme%'
AND SQL_TEXT NOT LIKE '%V$SQL%'
AND PARSING_USER_ID = SYS_CONTEXT('USERENV','CURRENT_USERID')
ORDER BY LAST_LOAD_TIME DESC)
WHERE ROWNUM < 2) S
WHERE S.HASH_VALUE = P.HASH_VALUE
AND S.CHILD_NUMBER = P.CHILD_NUMBER
ORDER BY ID
/Check the V$SQL_PLAN_STATISTICS_ALL view for more statistics available. In 10g there is a convenient function DBMS_XPLAN.DISPLAY_CURSOR which can show this information with a single call, but in 9i you need to do it yourself.
Note that "statistics_level=all" adds a significant overhead to the processing, so use with care and only when required:
http://jonathanlewis.wordpress.com/2007/11/25/gather_plan_statistics/
http://jonathanlewis.wordpress.com/2007/04/26/heisenberg/
Regards,
Randolf
Oracle related stuff blog:
http://oracle-randolf.blogspot.com/
SQLTools++ for Oracle (Open source Oracle GUI for Windows):
http://www.sqltools-plusplus.org:7676/
http://sourceforge.net/projects/sqlt-pp/ -
Tricky SQL query... how to get all data in a single query?
create table employee_definition (def_id number, def_name varchar(50));
insert into employee_definition values (100, 'EMAIL');
insert into employee_definition values (200, 'MOBILE_PHONE');
insert into employee_definition values (300, 'HOME_PHONE');
SQL> select * from employee_definition;
DEF_ID DEF_NAME
100 EMAIL
200 MOBILE_PHONE
300 HOME_PHONE
create table employee_data (def_id number, def_value varchar(20), emp_id number);
insert into employee_data values (100, '[email protected]', 123);
insert into employee_data values (200, '01232222', 123);
insert into employee_data values (300, '5555', 123);
insert into employee_data values (100, '[email protected]', 666);
insert into employee_data values (200, '888', 666);
insert into employee_data values (300, '999', 666);
insert into employee_data values (300, '444', 777);
SQL> select * from employee_data;
DEF_ID DEF_VALUE EMP_ID
100 [email protected] 123
200 01232222 123
300 5555 123
100 [email protected] 666
200 888 666
300 999 666
300 999 777
7 rows selected.I'm supposed to create a SQL that will return me the email, mobile_phone, and home_phone for a set of employees. The result will be something like this:
EMPLOYEE ID | HOME_PHONE | MOBILE_PHONE | EMAIL
123 | 5555 | 01232222 | [email protected]
666 | 999 | 888 | [email protected]
777 | 444 | null | nullThe thing I'm finding difficulty here is that the same column is used to store different values, based on the value in employee_definition table (something like a key/value pair). If I do:
SQL> select emp_id, def_value as email from employee_data, employee_definition
2 where employee_data.def_id = employee_definition.def_id
3 and employee_definition.def_name = 'EMAIL';
EMP_ID EMAIL
123 [email protected]
666 [email protected]'s partially ok.. I'm just getting the definition for 'EMAIL'. But how can I get all the values in a single query, knowing that the column stores different values based on def_name?Oh no, not again.
Entity attribute models always seem like a great idea to people who have been in the profession for five minutes and lack any kind of fundamental knowledge.
It staggers me that someone with 2,345 posts still believes "you need a 'detail table' for [storing multiple telephone numbers]"
"A person can have multiple telephone numbers" is not an excuse to build a tired person_attribute table. Niether is the bizarre proposal by someone with over 4k posts who should know better in an earlier post that EAV models are necessary to support temporal fidelity.
Taken to it's logical conclusion, EAV modelling leads to just two application tables. THINGS and THING_ATTRIBUTES. And when you consider that a THING_ATTRIBUTE is also a THING, why not roll those two tables up into one also? Hmmm, what does THINGS and THING_ATTRIBUTES look like? I know, TABLES and COLUMNS. Who would've guessed? SQL already provides the completely flexible extensible attribute model the advocates of EAV proscribe. But it also has data types, physical data independence, constraints and an efficient query language which EAV does not.
EAV modelling errodes the semantics of the attributes which are bundled into the "attribute" table.
There is no point in storing 12 different phone numbers with implied functional dependency to unconstrained and often repeating notional attributes like "MOBILE", "LANDLINE", "WORK", err, "WORK2", err, "MOBILE2", err, ... when this phone type attribute has no semantic value. When you want to call someone, you invariably want to retrive the prefered_phone_number which may depend on a time of day, or a call context.
These things need to be modelled properly (i.e normalised to BCNF) within the context of the database. -
A more efficient way to assure that a string value contains only numbers?
Hi ,
I'm using Oracle 9.2.0.6.
I was curious to know if there was any way I could write a more efficient query to determine if a string value contains only numbers.
Here's my current query. This SQL is from a sub query in a Join clause.
select distinct cta.CUSTOMER_TRX_ID, to_number(cta.SALES_ORDER) SALES_ORDER
from ra_customer_trx_lines_all cta
where length(cta.SALES_ORDER) = 6
and cta.SALES_ORDER is not null
and substr(cta.SALES_ORDER,1,1) in('1','2','3','4','5','6','7','8','9','0')
and substr(cta.SALES_ORDER,2,1) in('1','2','3','4','5','6','7','8','9','0')
and substr(cta.SALES_ORDER,3,1) in('1','2','3','4','5','6','7','8','9','0')
and substr(cta.SALES_ORDER,4,1) in('1','2','3','4','5','6','7','8','9','0')
and substr(cta.SALES_ORDER,5,1) in('1','2','3','4','5','6','7','8','9','0')
and substr(cta.SALES_ORDER,6,1) in('1','2','3','4','5','6','7','8','9','0')This is a string where I'm finding A-Z-a-z characters and '/' and '-' characters in all 6 positions, plus there are values that are longer than 6 characters. That's what the length(cta.SALES_ORDER) = 6 is for. Also, of course. some cells are NULL.
So the question is, is there a more efficient way to screen out only the values in this field that are 6 character numbers or is what I have the best I can do?
Thanks,I appreciate all of your very helpfull workarounds. The cost is a little better in all cases than my original where clause.
To address the discussion that's popped up about design from this question, I can say a few things that should clear , at least, my situation up.
First of all this custom quoting , purchase order , and sales order entry system WAS written by a bunch a of 'bad' coders who didn't document their work and then left. We don't even have an ER diagram
The whole project that I'm only a small part of is literally trying to put Humpty Dumpty together again and then move it from a bad custom solution into Oracle Applications.
We're rebuilding, documenting, and doing ETL. This is one of your prototypical projects from hell.
It's a huge database project so we're taking small bites as a time. Hopefully, somewhere right before Armageddon hits, this thing will be complete.
But until then,..., well,..., you know the drill.
Thanks Again. -
Partition Table Query taking Too Much Time
I have created partition table and Created local partition index on a column whose datatype is DATE.
Now when I Query table and use index column in the where clause It is scaning all the table (Full scan) . The quey is :
Select * From mytable
where to_char(transaction_date, 'DD-MON-YY') = '01-Aug-07';
I have to use to_char function not to_date due to Front end application problem.Before we go too far with this, if you manually query with TO_DATE on the variable instead of TO_CHAR on the column, does the query actually use the index?
The TO_CHAR on the column will definitely stop Oracle from using any index on the column. If the query will use the index if you TO_DATE the variable, as I see it, you have three options. First, fix the application problem that won't let you use TO_DATE from the application. Second, change the application to call a function returning a ref cursor, get the date string as a parameter to the function, and do the TO_DATE in the function.
Third, you could consider creating a function-based index on TO_CHAR(transaction_date, 'dd-Mon-yy'). This would be the least desirable option, particularly if you would also be selecting records based on a range of transaction_dates, since it loses a lot of information that the optimizer could use in devising an efficient query plan. It could also change your results for a range scan.
John -
How to Efficiently Sample a Fixed Number of Rows
Good afternoon. I need to select a specific number of random rows from a table, and while I believe my logic is right it's taking too long, 30 minutes for a routine data size. Hopefully someone here can show me a more efficient query. I've seen the SAMPLE function, but it just randomly selects rows on a one-by-one basis, without a guaranteed total count.
This is the idea:
INSERT INTO Tmp_Table (Value, Sequence) SELECT Value FROM Perm_Table, DBMS_RANDOM.VALUE;
SELECT Value FROM Tmp_Table WHERE ROWNUM <= 1234 ORDER BY Sequence;I'd need to put the ORDER BY in a subselect for ROWNUM to work correctly, but anyway that's just an illustration. My actual need is a little more complicated. I have many sets of data; each set has many rows; and for each set I need to return a specific (different) number of rows. Perhaps project A has three rows in this table, and I want to keep two of them; project B has two rows, and I want to keep one of them. So I need to identify, for each row, whether it's valid for that project. This is what my data looks like:
Project Person Sequence Position Keeper
A Bill 1234 1 Yes
A Fred 5678 3 No
A George 1927 2 Yes
B April 5784 2 No
B Janice 2691 1 YesI populate Sequence with random values, then calculate the position of each person within their project, and finally discard people who's Position is greater than Max_Targets for the Project. Fred and April have the highest random numbers, so they're cut. It's not the case that I'm just trimming one person from each project; the actual percentage kept will range from zero to 100.
Populating the list with random values is not time-consuming, but calculating Position is. This is my code:
UPDATE Tmp_Targets T1
SET Position =
SELECT
COUNT(*)
FROM
Perm_Targets PT1
INNER JOIN Perm_Targets PT2 ON PT1.Project = PT2.Project
INNER JOIN Tmp_Targets T2 ON PT2.Target = T2.Target
WHERE
T1.Target = PT1.Target
AND T2.Sequence <= T1.Sequence
);The Target fields are PKs, and the Project and Sequence fields are indexed. Is there a better way to approach this? I could write a cursor that pulls out project codes and performs the above operations for each project in turn; that would be logically simpler and possibly faster. Has anyone here addressed a similar problem before? I'd appreciate any ideas.
This is on 9.2, in case it matters. Thank you,
JonathanYou've not given any indication of how max targets for a given project is determined, so for my example I'm using the ceiling of 1/2 of the number of records in each project which gives the same number of yes and no responses per project as you had:
with dta as (
select 'A' project, 'Bill' person from dual union all
select 'A', 'Fred' from dual union all
select 'A', 'George' from dual union all
select 'B', 'April' from dual union all
select 'B', 'Janice' from dual
), t1 as (
select project
, person
, row_number() over (partition by project order by dbms_random.value) ord
, count(*) over (partition by project) cnt
, rownum rn
from dta
select project
, person
, ord
, cnt
, case when ord <= ceil(cnt/2) then 'Yes' else 'No' end keep
from t1
order by rn
PROJECT PERSON ORD CNT KEEP
A Bill 2 3 Yes
A Fred 3 3 No
A George 1 3 Yes
B April 1 2 Yes
B Janice 2 2 No
5 rows selectedIn this example I use an analytic function to assign a random ordering for each record within a project in the middle query, in the final output query I am determining the yes no status based on the order within a project and the count of records in the project. If you had a table of projects indicating the thresh hold you could join to that and use the thresh hold in place of the ceil(cnt/2) portion of my inequality in the case statement. -
Query on column with comma separated values
I have a proposed table with unnormalized data like the following:
ID COLA COLB REFLIST
21 xxx zzz 24,25,78,412
22 xxx xxx 21
24 yyy xxx 912,22
25 zzz fff 433,555,22
.. ... ... ...There are 200 million rows. There is maximum of about 10 IDs in the REFLIST, though typically two or three. How could I efficiently query this data on the REFLIST column? e.g. something like:
SELECT id FROM mytable WHERE :myval in reflistLogically there is a many to many relationship between rows in this table. The REFLIST column contains pointers to ID values elsewhere in the table. The data could be normalized so that the relationship keys are in a separate table (in fact this is the current solution that we want to change).
ID REF
21 24
21 25
21 78
21 412
22 21
24 912
... ...The comma separated list seems instinctively like a bad idea, however there are various reasons for proposing it. The main reason is because the source for this data has it structured like the REFLIST example. It is an OLTP-like system rather than a data warehouse. The source code (and edit performance) would benefit greatly from not having to maintain the relationship table as the data changes.
Going back to querying the REFLIST column, the problem seems to be building an approriate index for the data. The ideas proposed so far are:
<li>Make a materialized view that presents the relationships as normalized (e.g. as in the example with ID, REF columns above), then index the plain column - the various methods of writing the view SQL have been widely posted.
<li>Use a Oracle Text Index (not something I have ever had call to use before).
Any other ideas? Its Oracle 10.2, though 11g could be possible.
Thanks
JimSomething like this ?
This is test demo on my 11.2.0.1 Windows XP
SQL> create table test (id number,reflist varchar2(30));
Table created.
SQL> insert into test values (21,'24,25,78,412');
1 row created.
SQL> insert into test values (22,'21');
1 row created.
SQL> insert into test values (24,'912,22');
1 row created.
SQL> insert into test values (25,'433,555,22');
1 row created.
SQL> select * from test
2 where
3 ',' || reflist || ',' like '%,22,%';
ID REFLIST
24 912,22
25 433,555,22
SQL>Source:http://stackoverflow.com/questions/7212282/is-it-possible-to-query-a-comma-separated-column-for-a-specific-value
Regards
Girish Sharma
Edited by: Girish Sharma on Jul 12, 2012 2:31 PM -
Hi,
when I run this query:
SELECT a.*, d.C1
FROM t1 a, t2 b, t3 c, t4 d
WHERE C2 IS NOT NULL
AND C1 > '0005'
AND a.C3 = b.C4
AND NOT EXISTS (
SELECT *
FROM t5
WHERE C5 = C2
AND C6 = DECODE (b.C7,'AB', 0,
'BC', '555',
a.C3
AND a.C2 = c.C5
AND a.C8 = d.C8;It is taking lot of time (more 1 hour), I need some suggestions how to tune it.
I have noticed that If I remove the "NOT EXISTS" clause the query becomes very fast.
I'd like to know How Can I write more efficient query, and speed up existing code.
Thanks in advance!Below ddl and explan plan of the query:
CREATE TABLE t4
ID_C NUMBER NOT NULL,
C1 VARCHAR2(14 BYTE)
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 103K| 12M| | 451K (1)| 01:30:17 |
|* 1 | FILTER | | | | | | |
|* 2 | HASH JOIN | | 103K| 12M| | 57064 (1)| 00:11:25 |
| 3 | TABLE ACCESS FULL | t2 | 66 | 528 | | 3 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 103K| 11M| | 57059 (1)| 00:11:25 |
|* 5 | HASH JOIN | | 106K| 11M| 3440K| 57051 (1)| 00:11:25 |
|* 6 | TABLE ACCESS FULL | t4 | 106K| 2188K| | 2012 (2)| 00:00:25 |
|* 7 | TABLE ACCESS FULL | t1 | 6343K| 568M| | 22970 (2)| 00:04:36 |
|* 8 | INDEX UNIQUE SCAN | SYS_C0020000 | 1 | 6 | | 1 (0)| 00:00:01 |
|* 9 | TABLE ACCESS BY INDEX ROWID| t5 | 1 | 9 | | 4 (0)| 00:00:01 |
|* 10 | INDEX RANGE SCAN | IDX_C | 1 | | | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------- -
Tune the query with join and not exists
This is on 10g R2.
I have a query similar to :
Select A.*, C.*
From A inner join B on A.id = B.id
Left join C on A.kid = C.kid
Where not exists
(select * from D where A.fid = D.fid and A.stat = 2);
I want avoiding to use the NOT EXISTS in the last part of the query
I tried the autotrace explain of above and compared with others format and found no better execution plan than that. The explain plan indicated that there were long "table access full" operation on B, due to its little huge records, and a long operation of the "NESTED LOOPS OUTER". I had tried to replace the NOT EXISTS part with another LEFT JOIN in the FROM, but it went worse. So Anyone can suggest a better way? or it is the most efficient query I can get?Here is the tkprof output
from baandb.ttfacr200201 a
inner join baandb.ttfgld106201 c on (a.t$ttyp = c.t$otyp and a.t$ninv = c.t$odoc) and c.t$leac like :"SYS_B_0"
left join baandb.ttfgld910201 d on c.t$dim2 = d.t$dimx and d.t$dtyp = :"SYS_B_1"
where not exists
(select * from baandb.tcisli205201 b
where a.t$ttyp = b.t$ityp and a.t$ninv = b.t$idoc)
and (a.t$trec = :"SYS_B_2" or a.t$trec = :"SYS_B_3" and t$tdoc = :"SYS_B_4")
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.01 0.01 0 0 0 0
Fetch 5 1.06 52.11 29925 45943 0 54
total 7 1.07 52.12 29925 45943 0 54
Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 31
Rows Row Source Operation
54 HASH JOIN RIGHT ANTI (cr=45943 pr=29925 pw=0 time=2317005 us)
9957 INDEX FAST FULL SCAN TCISLI205201$IDX1 (cr=39 pr=0 pw=0 time=54 us)(object id 16639)
10067 NESTED LOOPS OUTER (cr=45904 pr=29925 pw=0 time=68531937 us)
10067 HASH JOIN (cr=35837 pr=29925 pw=0 time=68471521 us)
10420 TABLE ACCESS FULL TTFACR200201 (cr=2424 pr=0 pw=0 time=20894 us)
33156 TABLE ACCESS FULL TTFGLD106201 (cr=33413 pr=29925 pw=0 time=117767552 us)
51 INDEX UNIQUE SCAN TTFGLD910201$IDX1 (cr=10067 pr=0 pw=0 time=53177 us)(object id 20402)
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 2 0.00 0.00 0 0 0 0
Execute 3 0.02 0.02 0 0 0 0
Fetch 6 1.06 52.11 29925 45943 0 55
total 11 1.08 52.14 29925 45943 0 55
Maybe you are looking for
-
How can I save a Adobe document to print duplex for other users.
I want to create a doc using Adobe and be able to set it to print duplex by other users without the user needed to go into printer settings. All the user has to do is click print on there computer and the doc. will print duplex. The users have Adobe
-
Video plays on iPhone 3G, but not iPhone 2G or iPod Touch 1st Gen
Hi all, We're creating videos to be played on iPhones and iPod touch's. The videos are working fine on my iPhone 3Gs but won't play on my iPod touch 1st gen or a 2G iPhone. I've had a look and the supported video list is exactly the same on all iPhon
-
the query that i wish to write is as follows : i want to parameterise the column name , table name, value and then retrieve the no of rows returned for that column, table and that value. Example Query : select ename from emp where empno = 1; here the
-
How do you get the pannel in your mac that shows your documents in icloud
I've upload some pages files to icloud and i don't know how to make the pannel in my mac to show up to get the documents. Help me please.
-
How to get HD's serial number??
Hi guys.. How to get serial number of hard disk in LINUX and MAC???? I dont find this.. Im waiting.. thx!