跨多个表优化INNER JOIN

时间:2019-05-23 21:42:13

标签: mysql sql

我已经在此站点上抓取了许多类似的回复,并在此过程中的多个阶段改进了我的代码。不幸的是,此三行查询仍然无法运行。

我有一个具有100k +行和大约30列的表,我可以过滤到3行(在此示例中),然后在21个小型查找表中执行INNER JOIN

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

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 - Lost connection to MySQL server during query

在此之后,我尝试对联接进行显式显示。

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

这是编写这种查询的最佳方法吗?我测试了子查询,以确保它只返回一个小表,并且可以确认它仅返回三行。

2 个答案:

答案 0 :(得分:2)

首先,您正在寻找最简单的方面

select
      mt.*
   from
      Master_Table mt
   where
      mt.indexed_col = 'value'

如果您在主表的第一个位置上的给定indexed_col上有一个索引(如果您有许多字段的复合索引),那可能是瞬时的。

现在,如果我在不同的查找列(总共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'

十年前,我有一个项目来处理类似的情况……主表有大约21+百万条记录,并且必须加入约30+的查找表。在超过24小时后运行查询后,系统爬网并查询死亡。

这也是在MySQL服务器上,而修复程序只是一个MySQL关键字...

Select STRAIGHT_JOIN mt.*, ...

通过将主表置于主要位置,where子句及其条件直接位于主表上,您就很好了。您知道表的关系。按照我向您提供的确切顺序进行查询。请勿尝试为此思考,并尝试根据可能具有较少记录数的子表进行优化,并以某种方式认为这将有助于更快地进行查询...不会。

尝试使用STRAIGHT_JOIN关键字。我接受了正在处理的查询,并在大约1.5个小时内完成了该查询……它返回了2100万行,并带有所有相应的查找键描述以进行最终输出,因此仍然需要比3条记录更长的持续时间。

答案 1 :(得分:0)

首先,不要使用子查询。将查询写为:

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_table(value, lookup_col)lookup_table(id, data_point)

如果仍然存在性能问题,则有多种可能性。其中最重要的一点是结果集太大而无法在合理的时间内返回。要查看是否是这种情况,可以使用select count(*)来计算返回的行数。