使用 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;

这里是查询的解释:

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 之前获取一部分用户。 免责声明:我没有验证它是否更快,但过去有类似的经验,这会有所帮助。