查询语句调整思路
- 减少数据扫描量:
- 在
JOIN
操作前,通过条件过滤减少参与 JOIN
的数据量。例如,在 orders
表和 products
表 JOIN
时,先在 products
表中过滤出特定商品类别相关记录,再与 orders
表 JOIN
。示例如下:
-- 错误示范:先JOIN再过滤
SELECT COUNT(DISTINCT users.id)
FROM users
JOIN orders ON users.id = orders.user_id
JOIN products ON orders.product_id = products.id;
-- 正确示范:先过滤再JOIN
SELECT COUNT(DISTINCT users.id)
FROM users
JOIN orders ON users.id = orders.user_id
JOIN (SELECT id FROM products WHERE category = '特定商品类别') AS filtered_products ON orders.product_id = filtered_products.id;
- 合理使用
JOIN
类型:
- 如果数据量较大且主表和关联表有一对一或一对极少关系,优先使用
INNER JOIN
,因为 LEFT JOIN
等其他类型可能会产生更多的中间结果集。例如,若 users
表和 orders
表是一对一或一对极少关系,使用 INNER JOIN
:
SELECT COUNT(DISTINCT users.id)
FROM users
INNER JOIN orders ON users.id = orders.user_id
INNER JOIN products ON orders.product_id = products.id
WHERE products.category = '特定商品类别';
- 避免使用
SELECT *
:在 COUNT()
查询中,只选择需要的列,如 COUNT(users.id)
而不是 COUNT(*)
,这样可以减少数据传输量,虽然在 COUNT()
操作中性能提升可能不明显,但在其他查询场景中有帮助。
索引优化思路
- 创建复合索引:
- 在
orders
表上,创建包含 user_id
和 product_id
的复合索引,例如 CREATE INDEX idx_user_product ON orders(user_id, product_id);
。这样在 JOIN
操作时,数据库可以更快定位到相关记录。
- 在
products
表上,对 category
列创建索引,如 CREATE INDEX idx_product_category ON products(category);
,以便快速过滤特定商品类别。
- 覆盖索引:
- 如果查询只涉及索引列的数据,创建覆盖索引可以避免回表操作。例如,在
users
表上,如果查询只需要 id
列,并且已经有 id
为主键索引,那么可以利用此索引来避免回表获取其他列数据。
- 索引维护:定期检查索引的使用情况和碎片情况,对于不再使用的索引及时删除,对于碎片化严重的索引进行重建或优化,以提高索引性能。例如,在 MySQL 中,可以使用
ANALYZE TABLE
语句来更新索引统计信息,帮助查询优化器做出更好的执行计划。