Reputation: 231
A topics table contains 22k topics (not that much). A topics_ignore table for users contains only 33 topics. I am using this SQL query to get the topic count for each user without the ignored topics.
SELECT
COUNT(t.topic_id) AS num_topics
FROM topics t
LEFT JOIN topics_ignore i ON i.topic_id = t.topic_id AND i.user_id = 2
WHERE t.forum_id = 1
AND i.topic_id IS NULL
I added already two indexes on the topics table (topic_id, forum_id) and one index on topics_ignore table (topic_id)
The elapsed time is still 0.11015 seconds while other queries are in this range 0.00010s.
How can I benefit from using indexes or how to make this query faster?
Thank you
Upvotes: 0
Views: 1673
Reputation: 1269753
For this query:
SELECT COUNT(t.topic_id) AS num_topics
FROM topics t LEFT JOIN
topics_ignore i
ON i.topic_id = t.topic_id AND i.user_id = 2
WHERE t.forum_id = 1 AND i.topic_id IS NULL;
You want two indexes:
topics(forum_id, topic_id)
topics_ignore(topic_id, user_id)
The order of the columns in the indexes is important, so the first index is different from the index in your question.
Upvotes: 0
Reputation: 17
SELECT /*+RESULT_CACHE*/
COUNT(t.topic_id) AS num_topics
FROM topics t
LEFT JOIN topics_ignore i ON i.topic_id = t.topic_id AND i.user_id = 2
WHERE t.forum_id = 1
AND i.topic_id IS NULL
Result Cache is a new feature in Oracle 11g and it does exactly what its name implies, it caches the results of queries and puts it into a slice of the shared pool. If you have a query that is executed often and reads data that rarely changes, this feature can increase performance significantly.
Upvotes: 0
Reputation: 222462
I would start by rewriting the query with not exists
:
select count(*)
from topics t
where
not exists (select 1 from topics_ignore ti where ti.user_id = 2 and ti.topic_id = t.topic_id)
and t.forum_id = 1
Then, you can create the following index, so the subquery executes quickly:
topics_ignore(user_id, topic_id)
An index on topics(forum_id, topic_id)
might also help (not that the order of columns is different than in your original code).
That said, your query has a decent execution time already (0.1 sec), and your performance target (0.0001 sec) seems quite unreasonable.
Upvotes: 1