【问题标题】:Optimizing Left Join With Group By and Order By (MariaDb)使用 Group By 和 Order By (MariaDb) 优化左连接
【发布时间】:2022-01-28 19:59:18
【问题描述】:

我正在尝试优化 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;
  • 我需要它是左连接,因为我想包含未链接到车辆的用户。
  • 我需要 group by,因为我只希望每个用户有 1 个结果(并且不能保证 display_name 是唯一的)。
  • users 表大约有 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);

我正在寻找有关如何加快速度的想法。我尝试使用嵌套查询,但由于顺序是瓶颈,嵌套查询中的顺序被忽略,我相信这种尝试是徒劳的。

【问题讨论】:

标签: performance mariadb sql-order-by


【解决方案1】:

怎么样:

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

【讨论】:

  • 我唯一需要改变的就是将 order by 子句移动到子查询中。仍然非常高效,非常感谢。
  • 所以确实更快,不错,谢谢确认
【解决方案2】:
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; 



)

【讨论】:

  • 我在将 ORDER BY 更改为 'ORDER BY a.display_name' 后运行了它,但并没有显着加快速度。
【解决方案3】:

我怀疑实际上不是排序导致问题...如果您取消限制,我敢打赌,有序和未排序的版本最终会表现得非常接近。

根据您的实际查询是否与您发布的查询一样简单,您也许可以通过将 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 

如果这不起作用,您可能需要在一次选择中选择用户,然后在第二次选择中选择他们的车辆

【讨论】:

  • 即使没有限制,查询也很慢。
猜你喜欢
  • 2012-12-31
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 2017-02-06
相关资源
最近更新 更多