在左联接上使用SQL索引

  • 本文关键字:SQL 索引 mysql sql
  • 更新时间 :
  • 英文 :


一个主题表包含22k个主题(不多(。用户的topics_ignore表只包含33个主题。我使用这个SQL查询来获取每个用户的主题计数,而不包含被忽略的主题。

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

我已经在主题表(topic_id,forum_id(上添加了两个索引,在topics_ignore表(topic_id(上添加了一个索引

经过的时间仍然是0.11015秒,而其他查询在0.00010s的范围内

如何从使用索引中获益,或者如何加快查询速度?

谢谢

我首先要用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

然后,您可以创建以下索引,以便快速执行子查询:

topics_ignore(user_id, topic_id)

topics(forum_id, topic_id)上的索引也可能有所帮助(并不是说列的顺序与原始代码中的不同(。

也就是说,您的查询已经有了不错的执行时间(0.1秒(,而您的性能目标(0.0001秒(似乎非常不合理。

对于此查询:

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;

你想要两个索引:

  • topics(forum_id, topic_id)
  • topics_ignore(topic_id, user_id)

索引中列的顺序很重要,因此第一个索引与问题中的索引不同。

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是Oracle 11g中的一个新功能,它完全按照它的名字来做,它缓存查询的结果,并将其放入共享池的一部分。如果您有一个经常执行的查询,并且读取很少更改的数据,则此功能可以显著提高性能。

最新更新