簡體   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