SQL优化(MySQL)-连接操作时的优化规则

一句话总结:SQL语句中连接查询时,应选择较小的表作为外循环的表(外表)。其中较小的表是指占用块数较小的表。

原因

在MySQL的查询优化中,有时会提到“选择块数小的表为外表”。这里的“块数”实际上是指InnoDB存储引擎中的数据块(也叫“页”)。当我们谈到“选择块数小的表为外表”,通常是指在某些特定的联接操作中,从块数较小的表中获取数据可能会更高效。
为了理解这一点,我们需要先了解以下几点:InnoDB存储结构:InnoDB是MySQL的默认存储引擎,它使用一个聚簇索引来存储数据。每个表的数据实际上是按主键的顺序存储的。除了主键之外的数据,InnoDB还会维护一个辅助索引(也称为非聚簇索引或二级索引),该索引包含指向主键索引的指针。数据读取:当执行一个联接操作时,MySQL需要从两个表中获取数据。如果其中一个表的数据量很小,那么从该表中获取数据就会更快。因此,将块数小的表作为外表(outer join)可以减少需要读取的数据量,从而提高查询效率。优化器决策:MySQL的查询优化器会根据统计信息和其他因素来决定如何执行查询。有时,即使你明确地写了联接的顺序,优化器也可能选择一个不同的执行计划,因为它认为那样更高效。因此,当你考虑“选择块数小的表为外表”的建议时,你实际上是在基于一些经验性的观察来优化查询性能。但最终,最好的做法是定期检查查询的执行计划,确保它按照你预期的方式执行,并确保相关的表统计信息是最新的。

例子

假设我们有两个表:users 和 orders。

users 表存储了用户信息,并且有一个主键 user_id。
下面展示一些 内联代码片

//CREATE TABLE users (
    user_id INT PRIMARY KEY,
    name VARCHAR(50)
);

orders表存储了订单信息,并且有一个外键user_id,它引用 users表的user_id

// CREATE TABLE orders (
    order_id INT PRIMARY KEY,    user_id INT,    product VARCHAR(50),    FOREIGN KEY (user_id) REFERENCES users(user_id));

现在,如果我们想查询每个用户及其订单,我们可以使用以下查询:

// SELECT users.name, orders.product
FROM usersLEFT JOIN orders ON users.user_id = orders.user_id;

附:

当我们说某个表是“外表”,我们是在指代它在一个联接操作中的位置。在SQL中,LEFT JOIN、INNER JOIN等操作都会涉及到两个表的数据。其中一个表被放在“外表”的位置,另一个表被放在“内表”的位置。

在上述的例子中,users 表是外表,因为它首先出现在JOIN操作中。与此相对,orders 表是内表,因为它在JOIN条件之后出现。

选择哪个表作为外表并不是随意的,而是基于一些优化策略。例如,选择块数较小的表作为外表可以提高查询效率。但实际上,查询优化器会根据数据的统计信息和查询的具体情况来决定最佳的执行计划。

简而言之,外表是指在一个联接操作中首先出现的表,而内表则是在JOIN条件之后出现的表。