This question is pretty straight forward but the answer I'm thinking is not ..
I have a query that runs fast - under a second. But If I pass many values to the filter criteria it slows down a great deal.
For example, it runs fast like this:
SELECT * FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
But this same code runs very slow if I make the following addition:
SELECT * FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
AND MYVALUE IN ('A', 'B', 'C', 'D', 'E')
Is there anything that can be done with the SQL to amend this. My goal is to have the query run fast, preferably under a second.
I have tried GROUP BY, but it did not make a difference.
I've ruled out all possibilities and the issue is with the IN (multiple values)
section.
Any ideas?
This is too long for a comment.
How are you measuring the speed of the first query? One possibility is that you are measuring the speed to the first value being returned rather than the last value -- and Oracle finds it easy to returned values that meet the first condition. One way to check this is to use order by
because this requires getting all the rows (and then doing more work):
SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
ORDER BY othercol;
( ORDER BY
would typically be processing all the data.)
Assuming you are not making that mistake, another potential problem is the use of indexes. Oracle is usually pretty good about this. And, you can use the execution plan to see if the execution plans are the same. For instance, you might have an index on date_column
and one on myvalue
. Oracle might choose the wrong index.
If this is the case, you can create an index on (myvalue, datecol)
and trying running this query:
SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30) AND
MYVALUE = 'A';
If this runs fast, then try the index on your query. If that doesn't work, use UNION ALL
:
SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30) AND MYVALUE = 'A'
UNION ALL
SELECT *
FROM MYTABLE
WHERE DATE_COLUMN > TRUNC(SYSDATE-30) AND MYVALUE = 'B'
UNION ALL
. . .
1) find out the actual index being used for the 1st query (you may check the "explain plan"), then add a hint /*+index(MYTABLE MYINDEX)*/ to the 2nd SQL in order to ensure the same index is used for that as well
2) use the below SQL to force the sub-query to be processed first
SELECT * FROM (
SELECT /*+no_merge*/ ROWNUM row_num, t.* FROM MYTABLE t
WHERE DATE_COLUMN > TRUNC(SYSDATE-30)
) WHERE MYVALUE IN ('A', 'B', 'C', 'D', 'E')
I feel that whether a query is running faster or not can be checked by using explain plan to see what is happening internally. I would suggest:
Hope this helps to narrow down the issue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.