sql查询连接多个表 - 太慢(8个表)

33 sql performance join

我正在尝试将8个表连接成一个以创建其他应用程序使用的索引,我的查询就像:(我的mysql技能非常业余)

SELECT t1_id, t2_name, t3_name, t4_name, t5_name, 
       t6_name, t7_name, t8_name, t9_name 
FROM t1 
  LEFT JOIN t2 ON (t1_id = t2_id) 
  LEFT JOIN t3 ON (t3_id = t1_id) 
  LEFT JOIN t4 ON (t4_id = t1_id)
  LEFT JOIN t5 ON (t5_id = t1_id)
  LEFT JOIN t6 ON (t6_id = t1_id) 
  LEFT JOIN t7 ON (t7_id = t1_id)
  LEFT JOIN t8 ON (t8_id = t1_id)
  LEFT JOIN t9 ON (t9_id = t1_id)
Run Code Online (Sandbox Code Playgroud)

当我执行它时,我甚至无法看到查询结果,任何加速它的方法?:)赞赏任何种类的帮助,但最好只有一个查询(外部应用程序规则)

提前致谢

小智 53

我有一个类似的问题,几个查找表连接到一个所有id字段索引的大表.为了监视联接对查询时间执行的影响,我多次运行我的查询(限制到前100行),每次都向另一个表添加一个Join.加入12个表后,查询执行时间没有重大变化.当我加入第13个表时,执行时间跳到1秒; 第14桌4秒,第15桌20秒,第16秒90秒.

Keijro建议使用相关子查询而不是连接,例如

SELECT t1_id, 
        (select t2_name from t2 where t1_id = t2_id), 
        (select t3_name from t3 where t1_id = t3_id), 
        (select t4_name from t4 where t1_id = t4_id), 
        (select t5_name from t5 where t1_id = t5_id), 
        (select t6_name from t6 where t1_id = t6_id), 
        (select t7_name from t7 where t1_id = t7_id), 
        (select t8_name from t8 where t1_id = t8_id), 
        (select t9_name from t9 where t1_id = t9_id)  FROM t1
Run Code Online (Sandbox Code Playgroud)

显着提高查询性能.事实上,子查询似乎没有延长执行查询的时间(查询几乎是不稳定的).

我有点惊讶,因为我认为相关子查询比连接更糟糕.

  • 如果可以的话,我会给你更多的+1.我有完全相同的问题,这个解决方案完美无缺.来自MSSQL/Oracle背景,其中感知到的智慧是尽可能避免相关子查询,这非常违反直觉,但它有效.阅读它似乎可能是因为MySQL将连接作为嵌套循环处理. (3认同)

Nat*_*ley 29

根据表中的数据量,您可能需要在要连接的列上放置索引.查询速度通常很慢,因为缺少正确位置的索引.

也:

LEFT JOIN比INNER JOIN慢(虽然这取决于你正在做的事情) - 你能用内连接完成你想要的东西吗?

  • 可以很好地解释内部和左侧连接之间的差异:内部连接不包括未找到数据的行,左连接(或外部连接)的位置.也就是说,如果说t8缺少对应于t1_id的id,那么根本不会包含该行(即使有其他表具有该id) (5认同)
  • 同意这两点.使用INNER JOINS并确保您要加入的字段有索引. (4认同)

Jim*_*nke 5

如果您可以发布查询的解释计划,将会有所帮助。

但是,首先,您在联接中使用的所有字段上都有索引吗?就像是CREATE INDEX ix_t2_id on t2 (t2_id, t2_name);

除了联接,您可以执行类似的操作

SELECT t1_id, 
    (select t2_name from t2 where t1_id = t2_id), 
    (select t3_name from t3 where t1_id = t3_id), 
    (select t4_name from t4 where t1_id = t4_id), 
    (select t5_name from t5 where t1_id = t5_id), 
    (select t6_name from t6 where t1_id = t6_id), 
    (select t7_name from t7 where t1_id = t7_id), 
    (select t8_name from t8 where t1_id = t8_id), 
    (select t9_name from t9 where t1_id = t9_id) 
FROM t1 
Run Code Online (Sandbox Code Playgroud)

但是,有了一个好的查询计划者,那应该与联接没有什么不同。


u07*_*7ch 5

我们谈论了多少数据?可能是您拥有大量数据,并且在查询过程结束时运行where子句时,您需要在过滤之前加入大量数据.

在这种情况下,最好尽快过滤数据,这样如果你可以在第一个内部选择中限制来自T1的数据,那么所有其他连接将加入到一组更有限的数据中.

Select <your fields> from
(
Select * from t1 where t1_id = t1_value
) t1

Inner join t2
on t1.ID = t2.ID
...
Run Code Online (Sandbox Code Playgroud)

如果它不是大量的数据; 检查索引是否正确然后检查服务器类型的东西; 索引碎片; 磁盘队列等