我正在尝试将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)
我执行它时甚至看不到查询结果,有什么方法可以加快速度吗? :)赞赏任何类型的帮助,但最好只有一个查询(外部应用程序规则)
提前致谢
答案 0 :(得分: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
显着提高了查询性能。事实上,子查询似乎没有延长执行查询的时间(查询几乎是不稳定的)。
我有点惊讶,因为我认为相关子查询的性能比连接差。
答案 1 :(得分:28)
根据表中的数据量,您可能需要在要连接的列上放置索引。查询速度通常很慢,因为缺少正确的索引。
此外:
LEFT JOIN比INNER JOIN慢(虽然这取决于你正在做的事情) - 你能用内连接完成你想要的东西吗?
答案 2 :(得分:5)
我们谈论了多少数据?可能是您拥有大量数据,并且在查询过程结束时运行where子句,您需要在过滤之前加入大量数据。
在这种情况下,最好尽快过滤数据,这样如果你可以在第一个内部选择中限制来自T1的数据,那么所有其他连接将加入一组更有限的数据。
Select <your fields> from
(
Select * from t1 where t1_id = t1_value
) t1
Inner join t2
on t1.ID = t2.ID
...
如果它不是大量的数据;检查索引是否正确然后检查服务器类型的东西;索引碎片;磁盘队列等。
答案 3 :(得分:4)
如果您可以发布查询的解释计划,那会有所帮助。
但是,首先,您在连接中使用的所有字段都有索引吗?
像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
但是,如果有一个好的查询规划器,那么它应该与连接不同。
答案 4 :(得分:1)
如果您需要t1的所有行,并且您在其他表的主键(我猜它也是聚簇索引)上保持连接,则无法提高查询的速度。
要提高性能,您需要减少结果集或执行讨厌的技巧(例如,制作数据的非规范化副本)。
答案 5 :(得分:1)
根据您的查询计划,我可以得出结论,称为s
,n
和q
的表格没有关于它们正在加入的字段的索引。
由于这些表格中有很多行(笛卡尔积中约为400,000
行)而MySQL
只有JOIN
的行使用NESTED LOOPS
这真的需要永远。
在这些表上创建索引或将联接字段定义为PRIMARY KEY
。
答案 6 :(得分:0)
正如我所看到的,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子句的列上创建它。
答案 7 :(得分:-1)
根据您的SQL Server版本,只需将查询放入存储过程可能会产生很大的不同。在您首先尝试其他优化之后尝试这一点。(是的,我知道有缓存的执行计划和其他内部服务器优化,但在我的实际实际经验中,存储过程可以更快地执行。)