Mysql 在左连接上使用SQL索引

Mysql 在左连接上使用SQL索引,mysql,sql,Mysql,Sql,一个topics表包含22k个主题(不是那么多)。用户的topics\u 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_

一个topics表包含22k个主题(不是那么多)。用户的topics\u 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
我已经在topics表(topic\u id,forum\u id)上添加了两个索引,在topics\u ignore表(topic\u 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)
关于
主题(论坛id,主题id)
的索引也可能有帮助(并非列的顺序不同于原始代码)

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

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

对于此查询:

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;
您需要两个索引:

  • 主题(论坛id,主题id)
  • topics\u ignore(topic\u id,user\u id)

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

0.1秒对我来说似乎很快。这真的是个问题吗?如果是这样,请参阅:,并注意,有关查询性能的问题始终需要对给定查询进行解释请显示
解释选择…查询的其余部分,并显示您提到的在.0001秒内完成的查询及其解释输出,并显示
show CREATE TABLE topics
show CREATE TABLE topics\u ignore
的输出非常感谢您的参与。你的意思是我需要两个字段上的两个索引吗?如下所示:在主题上创建索引论坛主题id(论坛id,主题id)@拉斯维加斯。对我修正了答案中的错误。你好,GMB,你好,戈登·林诺夫,再次非常感谢你关注我的问题,感谢你花时间投资。我比较了你们的两种解决方案。起初,它们都是一个很大的改进。正如我所说,查询需要在0.11015s之前进行改进。随着GMB的改进,查询只需0.01423秒。伟大的通过Gordon的改进,查询只需要0.00943秒。我接受gorden的回答,但GMB也很有效。非常感谢。“topics\u ignore”已经有主题id的索引。是否必须删除此索引并添加此索引:在“topics\u ignore”上创建索引论坛主题id(用户id,主题id)@拉斯维加斯:从技术上讲,你不需要删除旧的索引,你只需要创建一个新的索引。谢谢你,新的索引超过了两列而不是一列,对吗?@拉斯维加斯:是的,没错。你好,GMB,你好,戈登·林诺夫,再次感谢你关注我的问题,谢谢你花时间投资。我比较了你们的两种解决方案。起初,它们都是一个很大的改进。正如我所说,查询需要在0.11015s之前进行改进。随着GMB的改进,查询只需0.01423秒。伟大的通过Gordon的改进,查询只需要0.00943秒。我接受gorden的回答,但GMB也非常有效。