Mysql 跨多个表优化内部联接
我在这个网站上搜索了许多类似的回复,并在几个阶段改进了我的代码。不幸的是,这个3行查询仍然无法运行 我有一个包含100k+行和大约30列的表,我可以将其中的行过滤到3行(在本例中),然后在21个小型查找表中执行Mysql 跨多个表优化内部联接,mysql,sql,Mysql,Sql,我在这个网站上搜索了许多类似的回复,并在几个阶段改进了我的代码。不幸的是,这个3行查询仍然无法运行 我有一个包含100k+行和大约30列的表,我可以将其中的行过滤到3行(在本例中),然后在21个小型查找表中执行内部联接 在我的第一次尝试中,我很懒惰,使用隐式连接 SELECT `master_table`.*, `lookup_table`.`data_point` x 21 FROM `lookup_table` x 21 WHERE `master_table`.`indexed_col`
内部联接
在我的第一次尝试中,我很懒惰,使用隐式连接
SELECT `master_table`.*, `lookup_table`.`data_point` x 21
FROM `lookup_table` x 21
WHERE `master_table`.`indexed_col` = "value"
AND `lookup_table`.`id` = `lookup_col` x 21
查询似乎已超时:
#2013-查询期间与MySQL服务器的连接中断
在这之后,我尝试对连接进行明确说明
SELECT `master_table`.*, `lookup_table`.`data_point` x 21
FROM `master_table`
INNER JOIN `lookup_table` ON `lookup_table`.`id` = `master_table`.`lookup_col` x 21
WHERE `master_table`.`indexed_col` = "value"
结果还是一样。然后我意识到,查询可能首先尝试执行连接,然后通过WHERE
子句进行过滤。因此,在进一步研究之后,我了解了如何应用子查询首先执行筛选,然后对新创建的表执行联接。这就是我得到的,它仍然返回相同的错误。我有没有办法进一步改进这个查询
SELECT `temp_table`.*, `lookup_table`.`data_point` x 21
FROM (SELECT * FROM `master_table` WHERE `indexed_col` = "value") as `temp_table`
INNER JOIN `lookup_table` ON `lookup_table`.`id` = `temp_table`.`lookup_col` x 21
这是写这种查询的最佳方式吗?我测试了子查询,以确保它只返回一个小表,并且可以确认它只返回三行。首先,不要使用子查询。将查询编写为:
SELECT mt.*, lt.`data_point`
FROM `master_table` mt INNER JOIN
`lookup_table` l
ON l.`id` = mt.`lookup_col`
WHERE mt.`indexed_col` = value;
您需要的索引是master\u table(value,lookup\u col)
和lookup\u table(id,data\u point)
如果您仍然存在性能问题,那么有多种可能性。其中最重要的是结果集太大,无法在合理的时间内返回。要查看是否是这种情况,可以使用选择count(*)
来计算返回的行数。首先,不要使用子查询。将查询编写为:
SELECT mt.*, lt.`data_point`
FROM `master_table` mt INNER JOIN
`lookup_table` l
ON l.`id` = mt.`lookup_col`
WHERE mt.`indexed_col` = value;
您需要的索引是master\u table(value,lookup\u col)
和lookup\u table(id,data\u point)
如果您仍然存在性能问题,那么有多种可能性。其中最重要的是结果集太大,无法在合理的时间内返回。要查看是否是这种情况,您可以使用选择count(*)
来计算返回的行数。首先,从最简单的方面来看
select
mt.*
from
Master_Table mt
where
mt.indexed_col = 'value'
如果主表上的索引位于第一个位置的给定索引列上(如果有多个字段的复合索引),那么这可能是即时的
现在,如果我在不同的查找列(总共21列)上正确地理解了您的意思,那么在本文中,您只是简化了这些列,以实现冗余,但实际上做了一些
select
mt.*,
lt1.lookupDescription1,
lt2.lookupDescription2,
...
lt21.lookupDescription21
from
Master_Table mt
JOIN Lookup_Table1 lt1
on mt.lookup_col1 = lt1.pk_col1
JOIN Lookup_Table2 lt2
on mt.lookup_col2 = lt2.pk_col2
...
JOIN Lookup_Table21 lt21
on mt.lookup_col21 = lt21.pk_col21
where
mt.indexed_col = 'value'
十多年前我有一个项目处理类似的情况。。。主表有大约2100多万条记录,必须连接到大约30多个查找表。系统爬网和查询在运行查询超过24小时后死亡
这也是在MySQL服务器上,修复是一个MySQL关键字
Select STRAIGHT_JOIN mt.*, ...
通过让主表处于主位置,where子句及其条件直接位于主表上,您就很好了。您知道表之间的关系。按照我给你的顺序进行查询。不要试着为我考虑这个问题,试着基于一个可能记录数较少的辅助表进行优化,并以某种方式认为这将有助于加快查询速度。。。不会的
试试“直接连接”关键字。它接受了我正在处理的查询,并在大约1.5小时内完成了它。。。它返回了所有2100万行以及最终输出的所有相应的查找键描述,因此仍然需要比仅3条记录更长的时间。首先,在您要查找的最简单的方面
select
mt.*
from
Master_Table mt
where
mt.indexed_col = 'value'
如果主表上的索引位于第一个位置的给定索引列上(如果有多个字段的复合索引),那么这可能是即时的
现在,如果我在不同的查找列(总共21列)上正确地理解了您的意思,那么在本文中,您只是简化了这些列,以实现冗余,但实际上做了一些
select
mt.*,
lt1.lookupDescription1,
lt2.lookupDescription2,
...
lt21.lookupDescription21
from
Master_Table mt
JOIN Lookup_Table1 lt1
on mt.lookup_col1 = lt1.pk_col1
JOIN Lookup_Table2 lt2
on mt.lookup_col2 = lt2.pk_col2
...
JOIN Lookup_Table21 lt21
on mt.lookup_col21 = lt21.pk_col21
where
mt.indexed_col = 'value'
十多年前我有一个项目处理类似的情况。。。主表有大约2100多万条记录,必须连接到大约30多个查找表。系统爬网和查询在运行查询超过24小时后死亡
这也是在MySQL服务器上,修复是一个MySQL关键字
Select STRAIGHT_JOIN mt.*, ...
通过让主表处于主位置,where子句及其条件直接位于主表上,您就很好了。您知道表之间的关系。按照我给你的顺序进行查询。不要试着为我考虑这个问题,试着基于一个可能记录数较少的辅助表进行优化,并以某种方式认为这将有助于加快查询速度。。。不会的
试试“直接连接”关键字。它接受了我正在处理的查询,并在大约1.5小时内完成了它。。。它将返回所有2100万行以及最终输出的所有相应查找键描述,因此仍然需要比仅3条记录更长的持续时间。这是我在使用子查询之前第二次尝试得到的格式。你能提供一个为什么子查询是个坏主意的原因吗?正如问题正文中提到的,在我的测试用例中,查询只返回3行。这已由选择计数(*)
确认。查看您的查询语法,这不会导致JOIN
出现在执行WHERE
子句之前。如果是这样的话,在过滤到三行结果之前,连接操作将需要发生100000多次?@MowgliB@MowgliB请参阅我对原始问题的评论,关于为什么在没有子查询的情况下仍然首先处理WHERE。至于为什么在这种情况下不应该使用子查询;如果您有Gordon指出的索引,子查询将阻止外部查询使用子查询表的索引。@M