Query is taking long time to execute in Vertica - vertica

I have one query to execute which will return the data according to latest date in the table.
Query is like below:
SELECT
*
FROM
demo,
(select * from ACCOUNT where day_id=select max(day_id) from ACCOUNT)ACCOUNT,
(select * from CUSTOMER where day_id=select max(day_id) from CUSTOMER) CUSTOMER,
(select * from SBSCRPN where day_id=select max(day_id) from SBSCRPN) SBSCRPN,
(select * from TIME where DAY_ID=select max(DAY_ID) from TIME) TIME
WHERE
( CUSTOMER.DAY_ID=ACCOUNT.DAY_ID and CUSTOMER.PARTY_ID=ACCOUNT.PARTY_ID )
AND ( ACCOUNT.DAY_ID=SBSCRPN.DAY_ID and ACCOUNT.ACCT_ID=SBSCRPN.ACCT_ID )
AND ( CUSTOMER.ORG_PARTY_ID=demo.ORG_PARTY_ID )
AND ( TIME.DAY_ID=CUSTOMER.DAY_ID )
this query is taking huge time to execute.
But when am giving the latest date(day_id value) hardcoded in the table, its giving resp within 40-50 sec.
SELECT
*
FROM
demo,
(select * from ACCOUNT where day_id='2021-02-07')ACCOUNT,
(select * from CUSTOMER where day_id='2021-02-07') CUSTOMER,
(select * from SBSCRPN where day_id='2021-02-07') SBSCRPN,
(select * from TIME where DAY_ID='2021-02-07') from TIME) TIME
WHERE
( CUSTOMER.DAY_ID=ACCOUNT.DAY_ID and CUSTOMER.PARTY_ID=ACCOUNT.PARTY_ID )
AND ( ACCOUNT.DAY_ID=SBSCRPN.DAY_ID and ACCOUNT.ACCT_ID=SBSCRPN.ACCT_ID )
AND ( CUSTOMER.ORG_PARTY_ID=demo.ORG_PARTY_ID )
AND ( TIME.DAY_ID=CUSTOMER.DAY_ID )
So, can anyone please help me to understand why this is taking time whem am using max function in inlineview. Does anyone can help how we can get faster result without harcoded the value in the query.
FYI, few tables contains huge volume of data like below:
DEMO;
55624
ACCOUNT;
426415370 ~426M
CUSTOMER;
1827947548 ~1.8B
SBSCRPN;
582688964 ~582M
TIME;
11323

From the hard-coded solution you mentioned, calculating max values outside of your query can probably accelerate the query execution. In Vertica, you can define variables and pass them to your SQL queries. For example, :max can be used instead of select max(day_id) from account in your query where
\set max `vsql -At -c "select max(day_id) from account;"`
\echo :max
and then you can rewrite your query as follow:
select * from account where day_id=:max

Related

Iterate a select query for a set of varchar2 in oracle

I have a below select query
select * from BUSINESS_T
where store_code = '075'
and item_no in
(
select item_no from BUSINESS_T a
where store_code = '075'
and exists
(
select * from BUSINESS_T
where store_code = a.store_code
and item_no = a.item_no
and
(
VALID_FROM_DTIME between a.VALID_FROM_DTIME and a.VALID_TO_DTIME
or VALID_TO_DTIME between a.VALID_FROM_DTIME and a.VALID_TO_DTIME
or (VALID_FROM_DTIME > a.VALID_FROM_DTIME and a.VALID_TO_DTIME is null)
or (VALID_FROM_DTIME < a.VALID_FROM_DTIME and VALID_TO_DTIME is null)
)
and del_dtime is null
and not
(
a.rowid = rowid
)
)
)
order by item_no, VALID_FROM_DTIME
Need to run it for a array of store numbers {'071','072','073','074','075','076'}
This array should defined inside the query itself.
Nearly 400+ fixed store numbers are there. The above query has to be run for each store, at a time for one store , To find the overlapping in that particular store
If i run by passing the collection of store numbers, there is a chance items are common in many stores that will cause a problem.
You can still use in if you modify the first subquery to get return the store/item pairs, which handles the common items:
select * from BUSINESS_T
where (store_code, item_no) in
(
select store_code, item_no from BUSINESS_T a
where store_code in ('071','072','073','074','075','076')
...
Or with a collection:
select * from BUSINESS_T
where (store_code, item_no) in
(
select store_code, item_no from BUSINESS_T a
where store_code member of sys.dbms_debug_vc2coll('071','072','073','074','075','076')
...
db<>fiddle with very simple demo of the idea.
Use in:
select *
from business_t
where
class_unit_code in ('071', '072', '073', '074', '075', '076')
and b_type = 'CASH_AND_CARRY'
and delete_date is null
For this specific sequence of string values, we might try to shorten the predicate using a regex (although this is probably less efficient):
regexp_like(class_unit_code, '^07[1-6]$')
Or if the string always contains numeric values, we can convert and use a range comparison (which also is not as efficient as the first option - in that case, the column should have been created with a numeric datatype to start with):
to_number(class_unit_code) between 71 and 76

Oracle Select via loop in Stored Procedure

I'm trying to select data from a table based on a array of filters calculated from another query. I have tried to describe what I'm trying to accomplish
in pseudo code below.
SELECT Equipment, MIN(TIME) as FractionStart, MAX(TIME) as FractionEnd
INTO FRACTIONS
FROM DATA
WHERE ID = 1
GROUP BY (Equipment)
/* Pseudo code */
FOR EACH ROW IN FRACTIONS
INSERT INTO MYTABLE (SELECT * FROM EVENTTABLE WHERE EVTTIME BETWEEN ROW.FractionStart AND ROW.FractionEnd AND EVTAREA = ROW.Equipment);
FOR NEXT;
RETURN MYTABLE;
I have been looking at cursors, but I haven't figured out how I can add rows to them in a loop. Am I looking at the right functions? or is there a better way to solve this?
Can you try this?
INSERT INTO MYTABLE
(
SELECT * FROM EVENTTABLE te,
(
SELECT Equipment, MIN(TIME) as FractionStart, MAX(TIME) as FractionEnd
FROM DATA
WHERE ID = 1
GROUP BY (Equipment)
) td
WHERE te.EVTTIME BETWEEN td.FractionStart AND td.FractionEnd AND te.EVTAREA = td.Equipment
);

can i set up an SSRS report where users input parameters to a table

I have an oracle query that uses a created table as part of the code. Every time I need to run a report I delete current data and import the new data I receive. This is one column of id's. I need to create a report on SSRS in which the user can input this data into said table as a parameter. I have designed a simple report that they can enter some of the id's into a parameter, but there may be times when they need to enter in a few thousand id's, and the report already runs long. Here is what the SSRS code currently says:
select distinct n.id, n.notes
from notes n
join (
select max(seq_num) as seqnum, id from notes group by id) maxresults
on n.id = maxresults.ID
where n.seq_num = maxresults.seqnum
and n.id in (#MyParam)
Is there a way to have MyParam insert data into a table I would join called My_ID, joining as Join My_Id id on n.id = id.id
I do not have permissions to create functions or procedures in the database.
Thank you
You may try the trick with MATERIALIZE hint which normally forces Oracle to create a temporary table :
WITH cte1 AS
( SELECT /*+ MATERIALIZE */ 1 as id FROM DUAL
UNION ALL
SELECT 2 DUAL
)
SELECT a.*
FROM table1 a
INNER JOIN cte1 b ON b.id = a.id

Oracle - What is the order of statement when using functions for filter in where clause

Refer Table WORKQUEUELOG with columns (ID,QueueTypeId,CreateDateTime,WorkId,InQ,OutQ)
There is an index available for (QueueTypeId,CreateDateTime,Id)
When trying to read the first X number of records with following query it is going for a full table search.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
AND EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId ,
tbl.InQ ) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
We changed the query as following and started using the index for reading.
ie Validaiton function first and filter function as second.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId,
tbl.InQ ) = 1
AND EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
What is the order of processing the SQL statement in oracle .? left to right or right to left.
From the above example this seems to be right to left . is this a consistent behavior. Is there any other efficient way to write this query.?

Need to select column from subquery into main query

I have a query like below - table names etc. changed for keeping the actual data private
SELECT inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
I am selecting records from Invoice based on Order. i.e. all records from Invoice which are common with order records for today, based on those 3 columns...
Now I want to select Order_Num from Order in my select query as well.. so that I can use the whole thing to insert it into totally seperate table, let's say orderedInvoices.
insert into orderedInvoices(seq_no,..same columns as Inv...,Cr_dt)
(
SELECT **Order.Order_Num**, inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
)
?? - how to do I select that Order_Num in main query for each records of that sub query?
p.s. I understand that trunc(cr_dt) will not use index on cr_dt (if a index is there..) but I couldn't select records unless I omit the time part of it..:(
If the table ORDER1 is unique on CARRIER, PRO and N_DT you can use a JOIN instead of IN to restrict your records, it'll also enable you to select whatever data you want from either table:
select order.order_num, inv.*, trunc(sysdate)
from Invoice inv
join order ord
on inv.carrier = ord.carrier
and inv.pro = ord.pro
and inv.ndate = ord.n_dt
where trunc(order.cr_dt) = trunc(sysdate)
If it's not unique then you have to use DISTINCT to deduplicate your record set.
Though using TRUNC() on CR_DT will not use an index on that column you can use a functional index on this if you do need an index.
create index i_order_trunc_cr_dt on order (trunc(cr_dt));
1. This is a really bad name for a table as it's a keyword, consider using ORDERS instead.

Resources