使用 Group By 和 Order By 优化左连接 (MariaDb)
Optimizing Left Join With Group By and Order By (MariaDb)
我正在尝试优化 MariaDb 中的一个查询,该查询确实因 ORDER BY 子句而陷入困境。我可以在没有 ORDER BY 子句的情况下在十分之一秒内 运行 它,但它需要超过 25 秒。这是查询的要点:
SELECT u.id, u.display_name, u.cell_phone, u.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM users u
LEFT JOIN user_vehicles uv ON uv.user_id = u.id AND uv.current_owner=1
WHERE u.is_deleted = 0
GROUP BY u.id
ORDER BY u.display_name
LIMIT 0, 10;
- 我需要它是左连接,因为我想包括未链接到车辆的用户。
- 我需要分组依据,因为我只希望每个用户有 1 个结果(并且 display_name 不能保证是唯一的)。
- users table 有大约 130K 行,而 user_vehicles 有大约 230K 行。
这里是查询的解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE u index dms_cust_idx PRIMARY 4 null 124825 Using where; Using temporary; Using filesort
1 SIMPLE uv ref user_idx user_idx 4 awscheduler.u.id 1 Using where
我试过这两个索引来加快速度,但它们似乎作用不大。
CREATE INDEX idx_display_speedy ON users(display_name);
CREATE INDEX idx_display_speedy2 ON users(id, display_name, is_deleted, dms_cust_id);
我正在寻找有关如何加快速度的想法。我尝试使用嵌套查询,但由于顺序是瓶颈&嵌套查询中的顺序被忽略,我认为尝试是徒劳的。
with a as (
SELECT u.id, u.display_name, u.cell_phone, u.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM users u
LEFT JOIN user_vehicles uv ON uv.user_id = u.id AND uv.current_owner=1
WHERE u.is_deleted = 0
GROUP BY u.id
)
select * from a
ORDER BY u.display_name;
)
我怀疑这实际上不是导致问题的顺序......如果你取消限制,我敢打赌有序的和 un-ordered 版本最终会表现得非常接近。
根据您的实际查询是否像您发布的查询一样简单,您可能通过使用 RowNum() 作为 described here:
SELECT u.id, u.display_name, u.cell_phone, u.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM (
SELECT iu.id, iu.display_name, iu.cell_phone, iu.email
FROM users iu
WHERE iu.is_deleted = 0
ORDER BY iu.display_name) as u
LEFT JOIN user_vehicles uv ON uv.user_id = u.id AND uv.current_owner=1
WHERE ROWNUM() < 10
GROUP BY u.id
ORDER BY u.display_name
如果这不起作用,您可能需要 select 一个用户 select 然后 select 他们的车辆在一秒钟内 Select
怎么样:
WITH a AS (
SELECT u.id, u.display_name, u.cell_phone, u.email
FROM users u
WHERE u.is_deleted = 0
GROUP BY u.id
LIMIT 0, 10
)
SELECT a.id, a.display_name, a.cell_phone, a.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM a LEFT JOIN user_vehicles uv ON uv.user_id = a.id AND uv.current_owner=1
ORDER BY a.display_name;
我们的目的是在加入 user_vehicles
之前获取一部分用户。
免责声明:我没有验证它是否更快,但过去有类似的经验,这会有所帮助。
我正在尝试优化 MariaDb 中的一个查询,该查询确实因 ORDER BY 子句而陷入困境。我可以在没有 ORDER BY 子句的情况下在十分之一秒内 运行 它,但它需要超过 25 秒。这是查询的要点:
SELECT u.id, u.display_name, u.cell_phone, u.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM users u
LEFT JOIN user_vehicles uv ON uv.user_id = u.id AND uv.current_owner=1
WHERE u.is_deleted = 0
GROUP BY u.id
ORDER BY u.display_name
LIMIT 0, 10;
- 我需要它是左连接,因为我想包括未链接到车辆的用户。
- 我需要分组依据,因为我只希望每个用户有 1 个结果(并且 display_name 不能保证是唯一的)。
- users table 有大约 130K 行,而 user_vehicles 有大约 230K 行。
这里是查询的解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE u index dms_cust_idx PRIMARY 4 null 124825 Using where; Using temporary; Using filesort
1 SIMPLE uv ref user_idx user_idx 4 awscheduler.u.id 1 Using where
我试过这两个索引来加快速度,但它们似乎作用不大。
CREATE INDEX idx_display_speedy ON users(display_name);
CREATE INDEX idx_display_speedy2 ON users(id, display_name, is_deleted, dms_cust_id);
我正在寻找有关如何加快速度的想法。我尝试使用嵌套查询,但由于顺序是瓶颈&嵌套查询中的顺序被忽略,我认为尝试是徒劳的。
with a as (
SELECT u.id, u.display_name, u.cell_phone, u.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM users u
LEFT JOIN user_vehicles uv ON uv.user_id = u.id AND uv.current_owner=1
WHERE u.is_deleted = 0
GROUP BY u.id
)
select * from a
ORDER BY u.display_name;
)
我怀疑这实际上不是导致问题的顺序......如果你取消限制,我敢打赌有序的和 un-ordered 版本最终会表现得非常接近。
根据您的实际查询是否像您发布的查询一样简单,您可能通过使用 RowNum() 作为 described here:
SELECT u.id, u.display_name, u.cell_phone, u.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM (
SELECT iu.id, iu.display_name, iu.cell_phone, iu.email
FROM users iu
WHERE iu.is_deleted = 0
ORDER BY iu.display_name) as u
LEFT JOIN user_vehicles uv ON uv.user_id = u.id AND uv.current_owner=1
WHERE ROWNUM() < 10
GROUP BY u.id
ORDER BY u.display_name
如果这不起作用,您可能需要 select 一个用户 select 然后 select 他们的车辆在一秒钟内 Select
怎么样:
WITH a AS (
SELECT u.id, u.display_name, u.cell_phone, u.email
FROM users u
WHERE u.is_deleted = 0
GROUP BY u.id
LIMIT 0, 10
)
SELECT a.id, a.display_name, a.cell_phone, a.email,
uv.year, uv.make, uv.model, uv.id AS user_vehicle_id
FROM a LEFT JOIN user_vehicles uv ON uv.user_id = a.id AND uv.current_owner=1
ORDER BY a.display_name;
我们的目的是在加入 user_vehicles
之前获取一部分用户。
免责声明:我没有验证它是否更快,但过去有类似的经验,这会有所帮助。