我对与mysql相关的基本问题有疑问。考虑如下查询:
select *
from logdb_new.new_tbl_logrecord as alltable
where alltable.SessionID in (
select distinct SessionID from logdb_new.new_tbl_health
)
我想知道在执行此查询期间是否使用SessionID
表的new_tbl_health
上的索引。换句话说,告诉我查询的第二部分select distinct SessionID from logdb_new.new_tbl_health
是否首先执行以生成列表,然后执行主查询,或者它使用索引或new_tbl_health
上的任何内容来为其中的每一行查找sessionID new_tbl_logrecord。
我想减少查询的执行时间。 logdb_new.new_tbl_logrecord拥有近3000万条记录和logdb_new.new_tbl_health的不同SessionID 超过8万个结果。请让我知道是否有更好的查询,以减少执行时间。
答案 0 :(得分:4)
我不认为这里可以使用new_tbl_health.SessionID
上的索引,因为子查询的结果是中间结果。但是,我们可以尝试使用内部联接重写您的查询:
SELECT *
FROM logdb_new.new_tbl_logrecord t1
INNER JOIN logdb_new.new_tbl_health t2
ON t1.SessionID = t2.SessionID;
除了索引可能在这里可用之外,内部联接版本的优点在于,优化器现在可以自由选择要在联接的左侧/右侧显示哪个表。
作为附带说明,如果您想坚持当前的方法,我认为您可以删除不同的选择并仅使用:
SELECT SessionID FROM logdb_new.new_tbl_health
如果出现重复的SessionID
值,则在逻辑上不会更改查询的结果。但是调用DISTINCT
可能意味着查询计划可能必须进行一些汇总,也许是不必要的。
答案 1 :(得分:2)
我不认为in
会使用子查询上的索引(尽管优化器有时会做得很棒)。但是,您可以改用exists
,它将使用索引:
select lr.*
from logdb_new.new_tbl_logrecord lr
where exists (select 1
from logdb_new.new_tbl_health nth
where lr.SessionID = nth.SessionID
);
答案 2 :(得分:1)
查询:
select distinct SessionID from logdb_new.new_tbl_health
是“不相关的子查询”。大多数(如果不是全部)数据库将首先执行它,以获取ID列表,并将使用该列表从外部查询中选择行。
不利的一面是,该查询不能照原样进行“流水线化”,因此它将需要实现整个id值集。如果改为使用JOIN
,则该查询可能已经被流水线处理,并且需要更少的内存。无论如何,只有当子查询返回的id数量很大时,这种优化才有意义。不用担心。