Forcing an index in oracle - oracle

I have a query joining lots of fields. For some strange reason the index for one table is not being used at all( I use the index key clearly), instead it is doing a FULL table scan. I would like to force the index. We used to do optimizer hints in sybase. Is there a similar hint available in oracle?
For example, in sybase to join tables a, b, c and use myindex in table a, I would do :
SELECT a.*
FROM a(INDEX myindex),
b,
c
WHERE a.field1 = b.field1
AND b.field1 = c.field1
Question is how do I do this in oracle.
Thanks
Saro

Yes, there is a hint like that in Oracle. It looks something like this:
select /*+ index(a my_index) */ from a

Related

How to determine if an Index is required for my Oracle query

i would like to know if an index is required or would help to run the below query? i dont have any idea how can i analyze this question.
if some one can help please thanks
WITH C(A0_ID, A1_ID, A1_Col0)
AS (
SELECT
Table_1.ID AS A0_ID,
Table_2.ID AS A1_ID,
Table_2.Col0 AS A1_Col0
FROM Table_1 ,Table_2
WHERE Table_2.ID = Table_1.ID
AND Table_1.col1 = ?
AND BITAND(Table_1.col2, ?) <> ?
AND Table_2.col3 IN (?,?,?)
), T(A0_ID, A1_ID, A1_Col0) AS (
SELECT
A0_ID,
A1_ID,
A1_Col0
FROM C
WHERE A1_ID = ?
UNION ALL
SELECT
C.A0_ID,
C.A1_ID,
C.A1_Col0
from C
INNER JOIN T P ON C.A1_Col0 = P.A1_ID
) SELECT A0_ID, A1_ID, A1_Col0 FROM T
The main query selects from T with no post-processing (filtering, aggregation, sorting, etc.), so it doesn't require optimization.
T is a recursive CTE based on the subquery C. Therefore, T doesn't need optimization (unless you materialized it, but that's a different story).
Now, C can be optimized:
I would consider Table_1 as the driving table since it has an equality in the filtering criteria. It also, uses ID to join against Table_2. Therefore a good index for it is:
create index ix1 on Table_1 (col1, ID);
Then, to access Table_2 you'll need to get through ID that should be the main index column. You may add col3 to the index to somewhat improve the performance of the query; only a benchmark will tell if this is a wise idea. The index could look like:
create index ix2 on Table_2 (ID, col3); -- col3 is optional here
I would recommend you create these indexes and compare the performance that each option produces.

Hive Joins query

I have two tables in hive:
Table 1:
1,Nail,maher,24,6.2
2,finn,egan,23,5.9
3,Hadm,Sha,28,6.0
4,bob,hope,55,7.2
Table 2 :
1,Nail,maher,24,6.2
2,finn,egan,23,5.9
3,Hadm,Sha,28,6.0
4,bob,hope,55,7.2
5,john,hill,22,5.5
6,todger,hommy,11,2.2
7,jim,cnt,99,9.9
8,will,hats,43,11.2
Is there any way in Hive to retrieve the new data in table 2 that doesn't exist in table 1??
In other Databases tools, you would use a inner left/right. But inner left/right doesn't exist in Hive and suggestions how this could be achieved?
If you are using Hive version >= 0.13 you can use this query:
SELECT * FROM A WHERE A.firstname, A.lastname ... IN (SELECT B.firstname, B.lastname ... FROM B);
But I'm not sure if Hive supports multiple coloumns in the IN clause.
If not something like this could work:
SELECT * FROM A WHERE A.firstname IN (SELECT B.firstname FROM B) AND A.lastname IN (SELECT b.lastname FROM B) ...;
It might be wiser to concatenate the fields together before testing for NOT IN:
SELECT *
FROM t2
WHERE CONCAT(t2.firstname, t2.lastname, CAST(t2.val1 as STRING), CAST(t2.val2 as STRING)) NOT IN
(SELECT CONCAT(t2.firstname, t2.lastname, CAST(t2.val1 as STRING), CAST(t2.val2 as STRING))
FROM t1)
Performing sequential NOT IN sub-queries may give you erroneous results.
From the above example, a new record with the values ('nail','egan',28, 7.2) would not show up as new with sequential NOT IN statements.

How to optimise insert into..select Query?

I have a below insert query:
Insert into MAP_REL_ATTRIBUTE_PHYID
(MAP_RELNAME, MAP_ATTRNAME,MAP_ATTRVALUE,Source_PHYID,MAP_REL_PHYID)
Select a.map_relname,a.MAP_ATTRNAME,a.MAP_ATTRVALUE,a.id,b.ID
from key_attribute a ,
target_attribute b,
map_rel_phyid c
where a.id = c.Source_phyid
and b.id=c.map_rel_phyid
and a.map_relname = 'Connected By'
and a.map_attrname= b.attr_name
and dbms_lob.compare(a.MAP_ATTRVALUE,b.ATTR_VALUE)=0
For DDL and sample data please refer : Check here
This select query returns around 20 million records and thus taking infinite time to insert the data's into the table. I'm trying to optimise this query. I'm new to oracle. Based on the suggestions I found there can be two possibilities to optimise this:
Creating Indexes in which I'm not sure on which columns to index and what kind of indexes I should create.
Using Bulk Processing with BULK COLLECT and FORALL.
I don't know whether the above solutions are correct. Can somebody please suggest me on this? And let me know if there are any other way to improve the performance.
1) Use append hint for insert
2) Do not use any indexes if you select ALL rows from the table
3) Use parallel hints for insert and select (make sure that parallel DML is enabled first)
alter session enable parallel dml;
Insert /*+ APPEND PARALLEL(4) */ into MAP_REL_ATTRIBUTE_PHYID
(MAP_RELNAME, MAP_ATTRNAME,MAP_ATTRVALUE,Source_PHYID,MAP_REL_PHYID)
Select /*+ PARALLEL(4) USE_HASH(a b c) */ a.map_relname,a.MAP_ATTRNAME,a.MAP_ATTRVALUE,a.id,b.ID
from key_attribute a ,
target_attribute b,
map_rel_phyid c
where a.id = c.Source_phyid
and b.id=c.map_rel_phyid
and a.map_relname = 'Connected By'
and a.map_attrname= b.attr_name
and dbms_lob.compare(a.MAP_ATTRVALUE,b.ATTR_VALUE)=0;

Oracle: function based index using dynamic values

I have one complex SQL queries. One of the simple part of the queries looks like:
Query 1:
SELECT *
FROM table1 t1, table2 t2
WHERE t1.number = t2.number
AND UPPER(t1.name) = UPPER(t2.name)
AND t1.prefix = p_in_prefix;
Query 2:
SELECT *
FROM table1 t1, table2 t2
WHERE t1.number = t2.number
AND UPPER(t1.name) = UPPER(p_in_prefix || t2.name)
AND t1.prefix = p_in_prefix;
I have function based index on table1 as (number, UPPER(name)). I have function based index on my table2 as (number, UPPER(NAME)). p_in_prefix is a input parameter (basically a number).
Because of these indexes my Query 1 runs efficiently. But Query 2 has a performance issue, as in Query 2, 't2.name' is prefixed with p_in_prefix.
I can not create function based index for Query 2 because p_in_prefix is a input parameter and I don't know while creating index, what values it might hold. How to resolve performace issue in this scenario? Any hint/idea would be appreciated. If you require more information, please let me know.
Thanks.
Use AND UPPER(t1.name) = UPPER(p_in_prefix) || UPPER(t2.name).
As you have a function based index as UPPER(NAME) of table2, you should have an operand with the same expression in the query in order to make use of the function based index.
Using UPPER(p_in_prefix || t2.name) will not use the function based index as this does not match the function expression UPPER(NAME). Note here that using UPPER(t2.name) does not cause any problems as t2 is just a column alias.
Along with this, you can also pass an optimizer hint in your query in order to instruct the optimizer to use the index.
For more information read "Oracle Database 11g SQL" by Jason Price.
Also read Oracle Docs here and here and for optimizer hints here.

Is there a oracle hint to execute the where clauses in a specific order?

Consider the following two queries on a table where datecolumn is indexed -
Q1: select * from table where datecolumn > sysdate - 5;
Q2: select * from table where datecolumn > sysdate - 5 and datecolumn < sysdate - 1;
Q1 uses the index. But, Q2 somehow does a full table scan. Is it because oracle somehow chooses to execute "datecolumn < sysdate - 1" first ? In that case, is there a way to enforce order of execution of where clauses involving one column ?
You could specify an index hint, something like this:
select /*+ INDEX (table datecolumn_ix)*/
*
from table
where datecolumn > sysdate - 5 and datecolumn < sysdate - 1;
See Oracle Index Hint for more details.
Sure there is the index hint.
/*+ INDEX(table index_name) */
But, in your case maybe is better to collect statistics of your table.
Use DBMS_STATS.GATHER_TABLE_STATS('schema','table') procedure.
Oracle doesn't guarantee by default that your tables will be joining in the same order as you mentioned, thus you may use these hints:
ordered
https://docs.oracle.com/cd/B10500_01/server.920/a96533/hintsref.htm#5555
It will join your tables in the same order as you mentioned in where statement
leading
https://docs.oracle.com/cd/B10500_01/server.920/a96533/hintsref.htm#5730
you may specify the join orders of your tables
select /*+ leading (c b a) */
a.*
from
tablea a
, tableb b
, tablec c
where
a.some_id = b.some_id
and c.some_id = b.other_id
Also, for your Q2 you may try the between option
https://docs.oracle.com/cd/B28359_01/server.111/b28286/conditions011.htm

Resources