Mysql 为什么我的SELECT与子查询和联接速度如此之慢?
完成此查询需要10秒钟。但是,当我手动执行子查询并将Mysql 为什么我的SELECT与子查询和联接速度如此之慢?,mysql,performance,join,subquery,innodb,Mysql,Performance,Join,Subquery,Innodb,完成此查询需要10秒钟。但是,当我手动执行子查询并将t1.id限制更改为该列表时,它将在0.00秒内完成。我该怎么做才能让MySQL更快地执行查询 SELECT t1.col1, t2.col2, t3.col3 FROM t1, t2, t3 WHERE t1.t2id = t2.id AND t1.t3id = t3.id AND t1.id IN ( SELECT id FROM t4 WHERE blah = 123 ) 还有,为什么会发生这种情况?我想MySQL在对t1.id进行过
t1.id
限制更改为该列表时,它将在0.00秒内完成。我该怎么做才能让MySQL更快地执行查询
SELECT t1.col1, t2.col2, t3.col3
FROM t1, t2, t3
WHERE t1.t2id = t2.id AND t1.t3id = t3.id
AND t1.id IN ( SELECT id FROM t4 WHERE blah = 123 )
还有,为什么会发生这种情况?我想MySQL在对t1.id进行过滤之前会以某种方式连接所有三个表
t1、t2和t3分别包含3000、15和80行。子查询返回2-10行。重写不带子查询的查询:
SELECT t1.col1, t2.col2, t3.col3
FROM t1, t2, t3, (SELECT id FROM t4 WHERE blah = 123) AS t4
WHERE t1.t2id = t2.id AND t1.t3id = t3.id
AND t1.id=t4.id
确保在
WHERE
子句中使用的字段上有索引。重写查询,不使用子查询:
SELECT t1.col1, t2.col2, t3.col3
FROM t1, t2, t3, (SELECT id FROM t4 WHERE blah = 123) AS t4
WHERE t1.t2id = t2.id AND t1.t3id = t3.id
AND t1.id=t4.id
确保在WHERE
子句中使用的字段上有索引。尝试使用“内部联接”而不是“in”函数。
这样,您的sql指令将更具性能
SELECT t1.col1, t2.col2, t3.col3
FROM ((t1 INNER JOIN t2 ON t1.t2id = t2.id) INNER JOIN t3 ON t1.t3id = t3.id) INNER JOIN t4 ON t1.id = t4.id
WHERE t4.blah = 123
尝试使用“内部联接”而不是“IN”函数。
这样,您的sql指令将更具性能
SELECT t1.col1, t2.col2, t3.col3
FROM ((t1 INNER JOIN t2 ON t1.t2id = t2.id) INNER JOIN t3 ON t1.t3id = t3.id) INNER JOIN t4 ON t1.id = t4.id
WHERE t4.blah = 123
如果在语句上运行
EXPLAIN
,您可能会看到MySql在磁盘上创建了一个临时表:如果内联select(术语中的)中的数据足够大,通常会发生这种情况
简言之:
a) 使用EXPLAIN
查看数据库中发生了什么(并查看此行为如何随数据的增加而变化)
b) 尽可能避免内联子查询
c) 请记住,MySql只有一个嵌套的循环连接算法可供使用(其他数据库也使用哈希连接和合并连接算法),因此您可能会看到较小数据集的“更少”解析正在进行,但当达到临界点时,解析会突然下降。如果您对语句运行EXPLAIN
,您可能会看到MySql在磁盘上创建了一个临时表:如果内联select(您在
术语中的)中的数据足够大,通常会发生这种情况
简言之:
a) 使用EXPLAIN
查看数据库中发生了什么(并查看此行为如何随数据的增加而变化)
b) 尽可能避免内联子查询
c) 请记住,MySql只有一个嵌套的循环连接算法可供使用(其他数据库也使用哈希连接和合并连接算法),因此您可能会看到较小数据集的“更少”解析,但是当你到达一个临界点时会突然下降。尝试解释选择…
并使用显式连接,如内部连接…
@juergend从评论分数来看,你似乎是对的,但是使用显式内部连接连接t2和t3似乎没有任何改变。使用解释查看查询的执行计划。然后你可以看到它在哪里消耗了那么多的时间。将t1和t2,或者t1和t3与内部连接连接在一起不会改变什么<代码>从t1、t2、t3开始
与使用内部连接
@juergend相同抱歉,我对此不是很有经验。我可以看到这两个部分包含数千行,它们“使用where”而没有键。我仍然不明白为什么会发生这种情况。尝试解释选择…
并使用显式连接,如内部连接…
@juergend从评论分数来看,您似乎是对的,但是使用显式内部连接连接t2和t3似乎没有任何改变。使用解释查看查询的执行计划。然后你可以看到它在哪里消耗了那么多的时间。将t1和t2,或者t1和t3与内部连接连接在一起不会改变什么<代码>从t1、t2、t3开始
与使用内部连接
@juergend相同抱歉,我对此不是很有经验。我可以看到这两个部分包含数千行,它们“使用where”而没有键。我还是不明白为什么会这样。