在大学SQL课程中,关系数据库是关于表之间的JOINS。 所以我采用了一般的方法来先做所有必要的JOINS,然后选择数据,过滤时使用WHERE,GROUP BY当需要时。这样代码和逻辑就很简单。
但是,当事情变得比单个LEFT JOIN更复杂时,我的表现会非常糟糕。
今天我刚刚重写了JOIN查询,其执行时间为600秒 采用不同的方法: SELECT(SELECT ... WHERE ID = X.ID)FROM X 和 SELECT ... WHERE Y IN(SELECT ...) 现在它以0.0027秒结束。
我很沮丧,我在我加入的字段上使用索引,但性能太差了......
答案 0 :(得分:2)
LEFT JOIN
可能,但并非总是如此,强行先查看“左”表。
JOINs
(但不是LEFT JOINs
)加上触摸一个表的WHERE
,为优化工具提供了强大,可靠的提示,可以查看该表第一
JOIN
,加上WHERE
触及多个表格 - 优化工具有时会选择正确的“第一个”表格,有时则不会。
优化器通常从一个表中获取行(无论选择哪个最好开始),然后执行NLJ(嵌套循环连接)。这意味着一次一行地进入下一个表。这种“覆盖面”需要一个很好的指数。
IN ( SELECT ... )
,在旧版本中非常不是最理想的。现在,它可能变成“半连接”,就像EXIST ( SELECT ... )
一样,效率很高。有时手动这样做是有益的。
“爆炸 - 内爆”袭击了很多人。这是JOIN
和GROUP BY
的位置。分组主要是为了破坏由连接创建的大量行。有时,“派生”表可以是一个很好的优化。 (这是查询的手动重新制定。)
通常用于聚合的LEFT JOIN
可以折叠成这样的:SELECT ..., ( SELECT SUM(foo) FROM ... ) AS foos, ...
,从而减轻爆炸 - 内爆。
不了解“复合”索引的好处可能是此论坛上最常见的问题。
我应该絮絮叨叨吗?我怀疑我是否覆盖了1/4以上的案例。所以,我同意@leftjoin。以下是一些简单的提示:http://mysql.rjweb.org/doc.php/index_cookbook_mysql