Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 为什么我的SELECT与子查询和联接速度如此之慢?_Mysql_Performance_Join_Subquery_Innodb - Fatal编程技术网

Mysql 为什么我的SELECT与子查询和联接速度如此之慢?

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进行过

完成此查询需要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、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”而没有键。我还是不明白为什么会这样。