inner join / left join / right join / 性能优化

inner join

使用场景:当且仅当你只想返回多个表中匹配的行

1.语法

语法1:SELECT * FROM table1 INNER JOIN table2 ON table1.column = table2.column;

语法2:SELECT * FROM table1,table2 WHERE table1.column = table2.column;

语法3:SELECT * FROM table1 JOIN table2 ON table1.column = table2.column;

2.查询方式及结果

(1)查询会对 table1 的每一行的 column 值依次和 table2 的每一行的 column 值进行比较

(2)table1 的每一行的column可能在table2中找到一条/多条/没有column相等的数据,找到几条,那一行的查询结果就是几条

(3)注意:如果table1的某一行没有在table2中找到column 相等的值,那么查询结果中是不会有那一行的数据的

3.示例

(1)表:users

+----+----------+
| ID | Username |
+----+----------+
| 1  | Alice     |
| 2  | Bob      |
| 3  | Charlie |
+----+----------+

        表: orders

+---------+---------+
| OrderID | UserID  |
+---------+---------+
| 101     | 1       |
| 102     | 1       |
| 103     | 2       |
| 104     | 5      |
+---------+---------+

(2)查询

SELECT users.ID, users.Username, orders.OrderID
FROM users, orders
WHERE users.ID = orders.UserID;

(3)查询结果

 +----+----------+---------+
| ID | Username | OrderID |
+----+----------+---------+
| 1  | Alice    | 101     |
| 1  | Alice    | 102     |
| 2  | Bob      | 103     |
+----+----------+---------+

4.其它 

(1)在实际执行中,关系型数据库优化器通常会选择最有效的执行计划。

(2)推荐使用语法1的写法,逗号和 WHERE 子句的写法相对于 INNER JOIN 更为早期,可能在一些特殊情况下不被某些数据库系统完全支持或解释。

(3)在 INNER JOIN 中,连接的顺序是可以随意交换的,因为 INNER JOIN 是对称的。

(4) INNER可省略,JOIN 默认是指 INNER JOIN 。

         例如:

-- 查询1
SELECT users.ID, users.Username, orders.OrderID, order_details.Product
FROM users
INNER JOIN orders ON users.ID = orders.UserID
INNER JOIN order_details ON orders.OrderID = order_details.OrderID;

-- 查询2(连接条件的先后顺序交换了)
SELECT users.ID, users.Username, orders.OrderID, order_details.Product
FROM order_details
INNER JOIN orders ON order_details.OrderID = orders.OrderID
INNER JOIN users ON orders.UserID = users.ID;

left join

使用场景:当你想返回左表中的所有行,以及右表中与左表匹配的行

1.语法

SELECT * FROM table1 LEFT JOIN table2 ON table1.column = table2.column;

2.查询方式及结果

(1)拿左表的每一行的 column 去依次和右表的每一行的 column 对比。

(2)左表的每一行的 column 可能在右表中找到一条/多条/没有 column 相等的数据。

(3)如果左表的某一行没有在右表中找到 column 相等的值,查询结果中会有那一行的数据,但右表的列会显示为 NULL。

3.示例

(1)表:employees

+------+--------+-------------+
| EmpID| Name   | Department  |
+------+--------+-------------+
| 1    | Alice  | IT          |
| 2    | Bob    | HR          |
| 3    | Charlie| Finance     |
+------+--------+-------------+

        表: departments

+-------------+--------+
| Department  | Manager|
+-------------+--------+
| IT          | John   |
| HR          | Mike   |
| Sales       | Sam    |
+-------------+--------+

(2)查询

SELECT employees.Name, employees.Department, departments.Manager
FROM employees
LEFT JOIN departments ON employees.Department = departments.Department;

(3)查询结果

+--------+-------------+--------+
| Name   | Department  | Manager|
+--------+-------------+--------+
| Alice  | IT          | John   |
| Bob    | HR          | Mike   |
| Charlie| Finance     | NULL   |
+--------+-------------+--------+

4.其它 

(1)LEFT JOIN 也被称为 LEFT OUTER JOIN。

(2)LEFT JOIN 的关键点在于保留左表的所有行,即使在右表中没有匹配的行,也会显示左表的数据。

right join

使用场景:当你想返回右表中的所有行,以及左表中与右表匹配的行

1.语法

SELECT * FROM table1 RIGHT JOIN table2 ON table1.column = table2.column;

2.查询方式及结果

(1)拿右表的每一行的 column 去依次和左表的每一行的 column 对比。

(2)右表的每一行的 column 可能在左表中找到一条/多条/没有 column 相等的数据。

(3)如果右表的某一行没有在左表中找到 column 相等的值,查询结果中会有那一行的数据,但左表的列会显示为 NULL。

3.示例

(1)表:employees

+------+--------+-------------+
| EmpID| Name   | Department  |
+------+--------+-------------+
| 1    | Alice  | IT          |
+------+--------+-------------+

        表: departments

 +-------------+--------+
| Department  | Manager|
+-------------+--------+
| IT          | John   |
| IT          | Sam    |
| HR          | Sarah  |
+-------------+--------+

(2)查询

SELECT employees.Name, employees.Department, departments.Manager
FROM employees
RIGHT JOIN departments ON employees.Department = departments.Department;

(3)查询结果

+--------+-------------+--------+
| Name   | Department  | Manager|
+--------+-------------+--------+
| Alice  | IT          | John   |
| Alice  | IT          | Sam    |
| NULL | HR          | Sarah  |
+--------+-------------+--------+

4.其它 

(1)RIGHT JOIN 也被称为 RIGHT OUTER JOIN。

(2)RIGHT JOIN 的关键点在于保留右表的所有行,即使在左表中没有匹配的行,也会显示右表的数据。

性能优化

1. 避免使用 SELECT *,明确列出所需列

原因:

(1)可以减少传输和处理的数据量,提高效率。

(2)有些数据不能被不该看到的人看到。暴露的数据越多,风险越大。

2. 选择合理的字段类型

原因:

(1)可以减小存储空间的需求,还可以提高查询和索引的效率。

具体操作:

(1)使用VARCHAR代替CHARVARCHAR可以根据实际存储的数据长度节省空间。

        当然,对于手机号这种是固定长度的字符类型,还是推荐使用char,此时使用char可以提供一些存储和检索的性能优势。

(2)使用数据库原生的日期和时间类型,如DATETIMEDATETIME,而不是存储字符串形式的日期和时间。

        a. 数据库原生的日期和时间类型提供了强大的数据完整性保障,防止了存储无效或不一致的日期和时间,有助于维护数据库中数据的一致性。

        b. 数据库原生类型支持直接的日期和时间比较操作,轻松执行诸如"大于"、"小于"、"等于"等比较操作,而不需要进行字符串转换。这提高了查询和排序的效率。

        c. 数据库通常提供了丰富的内置函数,用于处理原生日期和时间类型。这些函数包括日期加减、提取部分日期时间等,方便了对日期和时间的处理。

3. 避免过多的 JOIN

原因:

(1)在可能的情况下,尽量减少 JOIN 操作的数量。过多的 JOIN 可能导致性能下降。

(2)JOIN太多,会导致开发人员看得头大。

4. 用连接查询代替子查询 

5. 小表连接大表

原理:先从小表中选择数据,再与大表进行连接,从而减少连接操作的数据量,提高查询性能。

例子:

users表

user_id username
1 Alice
2 Bob
3 Charlie

orders表

order_id user_id order_date total_amount
101 1 2023-01-15 50.00
102 2 2023-02-01 30.00
103 1 2023-03-10 20.00
104 3 2023-04-05 45.00

(1)users连接orders

SELECT xxx FROM users u JOIN orders o ON u.user_id=o.user_id WHERE u.user_id=1

执行步骤:

        a. 从users表中选择user_id=1的用户。这个操作涉及3次比较。

        b. 然后,对于从users中选择的每个user_id=1,从orders表中获取相应的行。对于从users中选择的每一行,都需要从orders表中获取4行。

       c. 总操作数:3(来自users表) + 1 * 4(来自orders表)= 7次操作。

(2)orders连接users
SELECT xxx FROM orders o JOIN users u ON o.user_id = u.user_id WHERE o.user_id=1

执行步骤:

        a. 从orders表中选择user_id=1的订单。这个操作涉及4次比较。

        b. 然后,对于从orders中选择的每个user_id=1,从users表中获取相应的用户行。对于从orders中选择的每一行,都需要从users表中获取3行。

        c. 总操作数:4(来自orders表) + 2 * 3(来自users表)= 10次操作。

6. 索引优化

猜你喜欢

转载自blog.csdn.net/qq_50853940/article/details/135091885