繁体   English   中英

用于计数查询的 MySQL 查询优化

[英]MySQL Query Optimization for for Count Query

我需要帮助优化此计数查询。 以下是表格:

activities
- activity_id (PRIMARY)
- item_id
- user_id
- created_at

INDEX: user_id_created_at (user_id, created_at)
INDEX: item_id (item_id)
retail_activities
- activity_id (PRIMARY)
- item_id
- created_at

INDEX: item_id (activity_id, item_id)
INDEX: item_id_created (activity_id, item_id, created_at)
users
- user_id (PRIMARY)
- is_private

INDEX: user_id_private (user_id, is_private)

目标

我想找到的物品和独特的用户在数的计数retail_activities发生过的日期范围,其中item_id活动表不等于item_id在retail_activities表,用户不是私有的。

基本上,我想找到发生的零售活动的总数以及在选定的 item_id 和选定的时间范围内执行的唯一用户总数。

所以查询将是(X 是一个整数,如 1234 - 如果项目是 ID)

SELECT count(retail_activities.item_id) as total_items, count(distinct activities.user_id) as total_users 
from activities 
inner join retail_activities on retail_activities.activity_id = activities.activity_id 
inner join users on users.user_id = activities.user_id 
where users.is_private = 0 and 
activities.item_id != retail_activities.item_id and retail_activities.item_id = X and
retail_activities.created_at > "2019-11-22 00:00:00"

此查询的 EXPLAIN 如下:

1   SIMPLE  retail_activities   item_id_created item_id_created 5   const   812856  Using where; Using index
1   SIMPLE  activities  eq_ref  PRIMARY PRIMARY 4   retail_activities.activity_id   1   Using where
1   SIMPLE  users   eq_ref  PRIMARY PRIMARY 4   activities.user_id  1   Using where

因为这个项目有很多活动(350k),所以运行很慢(8-25s)。 有什么办法可以加快速度吗?

对于此查询:

select count(*) as total_items, count(distinct a.user_id) as total_users 
from activities a join
     retail_activities ra
     on ra.activity_id = a.activity_id join
     users u
     on u.user_id = a.user_id 
where u.is_private = 0 and 
      a.item_id <> ra.item_id and
      ra.item_id = X
      ra.created_at > '2019-11-22';

我会推荐以下索引:

  • retail_activities(item_id, created_at, activity_id)
  • activities(activity_id, item_id) (如果activity_id是主键,则不需要)
  • users(user_id, is_private)

我建议您优化索引策略,并尽可能使用哈希索引。

根据 MySQL 文档:

作为复合索引的替代方案,您可以引入一个基于其他列信息“散列”的列。 如果此列很短、相当独特且已编入索引,则它可能比许多列上的“宽”索引更快。

此外,您不需要在retail_activities表中显式地INDEX: item_id (activity_id, item_id) 那是因为您已经创建了一个涉及它们的复合主键。 所以这也将作为一个索引。

并研究索引合并优化。 这是 MySQL 日志文档 并且,阅读优化器开关以确定理想的连接顺序以获得最佳性能。 以下是我认为您会发现有用的一些信息:

更改连接顺序。 完成此操作的方法包括连接顺序优化器提示(请参阅第 8.9.3 节“优化器提示”)、紧跟在 SELECT 之后的 STRAIGHT_JOIN 和 STRAIGHT_JOIN 连接运算符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM