Mysql 跨多个表优化内部联接

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`

我在这个网站上搜索了许多类似的回复,并在几个阶段改进了我的代码。不幸的是,这个3行查询仍然无法运行

我有一个包含100k+行和大约30列的表,我可以将其中的行过滤到3行(在本例中),然后在21个小型查找表中执行
内部联接

在我的第一次尝试中,我很懒惰,使用隐式连接

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