SQL查询语句
SELECT c.customer_name
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
JOIN order_items oi ON o.order_id = oi.order_id
WHERE YEAR(o.order_date) = 2023
GROUP BY c.customer_id, c.customer_name
HAVING SUM(oi.quantity) > 100;
查询计划剖析
- JOIN操作:
- 首先进行
customers
表和orders
表的连接(JOIN
),连接条件是c.customer_id = o.customer_id
。这个操作会生成一个临时表,其中包含两个表匹配的行。
- 接着,将上述临时表与
order_items
表进行连接,连接条件是o.order_id = oi.order_id
,再次生成一个更大的临时表,包含了所有相关联的数据。
- WHERE过滤:
- 使用
WHERE YEAR(o.order_date) = 2023
过滤出2023年下单的记录。这个操作在前面生成的临时表上进行,减少后续处理的数据量。
- GROUP BY和HAVING:
GROUP BY c.customer_id, c.customer_name
按照客户ID和客户名称对数据进行分组。
HAVING SUM(oi.quantity) > 100
对每个分组的数据进行统计,只保留购买产品数量总和超过100的分组。
优化索引
- 在
orders
表上:
- 为
customer_id
字段添加索引,因为它用于连接customers
表,索引可以加快连接操作。例如:CREATE INDEX idx_orders_customer_id ON orders(customer_id);
- 为
order_date
字段添加索引,因为它用于WHERE
子句过滤,能加速日期过滤。例如:CREATE INDEX idx_orders_order_date ON orders(order_date);
- 在
order_items
表上:
- 为
order_id
字段添加索引,因为它用于连接orders
表,有助于快速定位相关订单的订单项。例如:CREATE INDEX idx_order_items_order_id ON order_items(order_id);
- 为
quantity
字段添加索引,虽然在HAVING
子句中使用聚合函数,但该索引可能对数据检索有一定帮助,尤其在数据量较大时。例如:CREATE INDEX idx_order_items_quantity ON order_items(quantity);
优化查询结构
- 子查询优化:可以尝试将复杂的多表连接拆分成子查询,先在子查询中处理部分逻辑,减少主查询的复杂度。例如,先在子查询中过滤出2023年的订单及其订单项,再与
customers
表连接。
- 使用覆盖索引:如果查询涉及的字段都包含在索引中,数据库可以直接从索引中获取数据,避免回表操作,提高查询效率。例如,如果查询只需要
customer_name
和quantity
字段,可以创建一个包含customer_id
、customer_name
和quantity
的复合索引。