繁体   English   中英

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

[英]sql query joins multiple tables - too slow (8 tables)

我正在尝试将 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)

当我执行它时,我什至看不到查询结果,有什么方法可以加快速度吗? :) 任何类型的帮助表示赞赏,但最好只有一个查询(应用程序规则之外)

提前致谢

我也遇到了类似的问题,即几个查找表加入了一个具有所有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

大大提高了查询性能。 实际上,子查询似乎并没有延长执行查询的时间(查询几乎是瞬时的)。

我感到有些惊讶,因为我认为相关子查询的性能要比联接差。

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

也:

左联接比内部联接慢(尽管这取决于您要执行的操作)-是否可以通过内部联接完成所需的查找?

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

但是,首先,您在联接中使用的所有字段上都有索引吗? 类似于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 

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

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

在这种情况下,最好尽快过滤数据,因此,如果您可以在第一个内部中限制来自T1的数据,则所有其他联接都将联接到一组更有限的数据中。

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

Inner join t2
on t1.ID = t2.ID
...

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

如果需要t1的所有行,并且在其他表的主键(我想它也是聚簇索引)上保留了join,则无法提高查询速度。

为了提高性能,您需要减少结果集或执行令人讨厌的技巧(例如,对数据进行非规范化的副本)。

从您的查询计划中,我可以得出结论,称为snq的表在要连接的字段上没有索引。

由于这些表中有很多行(笛卡尔积中约有400,000行),而MySQL进行JOIN的唯一方法是使用NESTED LOOPS ,这将永远花费一生。

在这些表上创建索引或将连接的字段定义为PRIMARY KEY

当您使用的数据集太大以至于在执行连接时超出了工作内存时,连接会显着减慢。 Postgres 会在执行过程中将其工作保存到磁盘。 这就是为什么您可能只在第 n 个连接之后看到速度变慢的原因,而不管您正在连接哪些表,或者是否正确配置了索引。

就我而言, EXPLAIN只显示了几万行,没什么可写的。 但我了解到,即使在加入过程中发生减速,加入也可能不是问题。 在我的案例中,罪魁祸首是一个非常大的 uuid[] 列,其中包含很多条目。 我从我的查询中排除了这一列,它加快了一切。

正如我所看到的,t1表是与所有表连接的表,而不是将它们放在具有多个连接的单个查询中,您可以尝试使用类似这样的不同查询的并集。

SELECT  t1_id, t2_name 
FROM    t1 LEFT JOIN t2 ON (t1_id = t2_id)
union 
SELECT  t1_id, t3_name 
FROM    t1 LEFT JOIN t3 ON (t1_id = t3_id)

但是,在这种情况下,您将获得的结果将不会有8列,而只有1列。 不知道这是否是您可以使用的选项。

在您实现的任何解决方案中,您还必须做的一件事-在所有表上创建适当的索引。 索引列的最佳实践是在最常用于联接或where子句的列上创建索引。

根据您的SQL Server版本,仅将查询放入存储过程中可能会有很大的不同。 首先尝试其他优化后再尝试此操作。(是的,我知道有缓存的执行计划和其他内部服务器优化,但是根据我的实际经验,存储过程可以更快地执行。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM