簡體   English   中英

MySQL Select查詢執行緩慢

[英]Slow Execution of MySQL Select Query

我有以下查詢...

SELECT DISTINCT * FROM 
vPAS_Posts_Users 
WHERE (post_user_id =:id AND post_type != 4) 
AND post_updated >:updated 
GROUP BY post_post_id 
UNION 
SELECT DISTINCT vPAS_Posts_Users.* FROM PAS_Follow 
JOIN vPAS_Posts_Users ON 
( PAS_Follow.folw_followed_user_id = vPAS_Posts_Users.post_user_id ) 
WHERE (( PAS_Follow.folw_follower_user_id =:id AND PAS_Follow.folw_deleted = 0 ) 
OR ( post_type = 4 AND post_passed_on_by = PAS_Follow.folw_follower_user_id 
AND post_user_id !=:id )) 
AND post_updated >:updated 
GROUP BY post_post_id ORDER BY post_posted_date DESC LIMIT :limit

例如:id = 7:updated = 0.0:limit=40

我的問題是查詢需要大約一分鍾才能返回結果。 此查詢中有什么我可以做以加快結果的速度嗎?

我正在使用RDS

********編輯*********

我被要求使用EXPLAIN運行查詢,結果如下

從查詢中解釋結果

******** EDIT **********查看定義

CREATE ALGORITHM=UNDEFINED DEFINER=`MySQLUSer`@`%` SQL SECURITY DEFINER VIEW `vPAS_Posts_Users`
AS SELECT
   `PAS_User`.`user_user_id` AS `user_user_id`,
   `PAS_User`.`user_country` AS `user_country`,
   `PAS_User`.`user_city` AS `user_city`,
   `PAS_User`.`user_company` AS `user_company`,
   `PAS_User`.`user_account_type` AS `user_account_type`,
   `PAS_User`.`user_account_premium` AS `user_account_premium`,
   `PAS_User`.`user_sign_up_date` AS `user_sign_up_date`,
   `PAS_User`.`user_first_name` AS `user_first_name`,
   `PAS_User`.`user_last_name` AS `user_last_name`,
   `PAS_User`.`user_avatar_url` AS `user_avatar_url`,
   `PAS_User`.`user_cover_image_url` AS `user_cover_image_url`,
   `PAS_User`.`user_bio` AS `user_bio`,
   `PAS_User`.`user_telephone` AS `user_telephone`,
   `PAS_User`.`user_dob` AS `user_dob`,
   `PAS_User`.`user_sector` AS `user_sector`,
   `PAS_User`.`user_job_type` AS `user_job_type`,
   `PAS_User`.`user_unique` AS `user_unique`,
   `PAS_User`.`user_deleted` AS `user_deleted`,
   `PAS_User`.`user_updated` AS `user_updated`,
   `PAS_Post`.`post_post_id` AS `post_post_id`,
   `PAS_Post`.`post_language_id` AS `post_language_id`,
   `PAS_Post`.`post_type` AS `post_type`,
   `PAS_Post`.`post_promoted` AS `post_promoted`,
   `PAS_Post`.`post_user_id` AS `post_user_id`,
   `PAS_Post`.`post_posted_date` AS `post_posted_date`,
   `PAS_Post`.`post_latitude` AS `post_latitude`,
   `PAS_Post`.`post_longitude` AS `post_longitude`,
   `PAS_Post`.`post_location_name` AS `post_location_name`,
   `PAS_Post`.`post_text` AS `post_text`,
   `PAS_Post`.`post_media_url` AS `post_media_url`,
   `PAS_Post`.`post_image_height` AS `post_image_height`,
   `PAS_Post`.`post_link` AS `post_link`,
   `PAS_Post`.`post_link_title` AS `post_link_title`,
   `PAS_Post`.`post_unique` AS `post_unique`,
   `PAS_Post`.`post_deleted` AS `post_deleted`,
   `PAS_Post`.`post_updated` AS `post_updated`,
   `PAS_Post`.`post_original_post_id` AS `post_original_post_id`,
   `PAS_Post`.`post_original_type` AS `post_original_type`,
   `PAS_Post`.`post_passed_on_by` AS `post_passed_on_by`,
   `PAS_Post`.`post_passed_on_caption` AS `post_passed_on_caption`,
   `PAS_Post`.`post_passed_on_fullname` AS `post_passed_on_fullname`,
   `PAS_Post`.`post_passed_on_avatar_url` AS `post_passed_on_avatar_url`
FROM (`PAS_User` join `PAS_Post` on((`PAS_User`.`user_user_id` = `PAS_Post`.`post_user_id`)));

試試這個查詢:

SELECT * 
FROM 
    vPAS_Posts_Users 
WHERE 
    post_user_id =:id 
AND post_type != 4 
AND post_updated > :updated 
UNION 
SELECT u.* 
FROM vPAS_Posts_Users u
        JOIN PAS_Follow f ON f.folw_followed_user_id = u.post_user_id
WHERE 
    u.post_updated > :updated
AND (   (f.folw_follower_user_id = :id AND f.folw_deleted = 0) 
    OR  (u.post_type = 4 AND u.post_passed_on_by = f.folw_follower_user_id AND u.post_user_id != :id)
) 
ORDER BY u.post_posted_date DESC;
LIMIT :limit

其他改進

索引:確保在以下列上有索引:

  • PAS_User.user_user_id
  • PAS_Post.post_user_id
  • PAS_Post.post_type
  • PAS_Post.post_updated
  • PAS_Follow.folw_followed_user_id
  • PAS_Follow.folw_deleted
  • PAS_Post.post_passed_on_by

完成之后,請1-再次檢查性能(SQL_NO_CACHE),然后2提取另一個說明計划,以便我們可以調整查詢。


說明結果

說明結果

以下是有關查詢的一些建議,並首先對兩個結果集使用UNION進行查看,這可能會使查詢工作緩慢,而可以使用UNION ALL

為什么我要讓您使用UNION ALL

原因是UNION ALLUNION使用臨時表來生成結果。執行速度的差異是因為UNION要求內部臨時表帶有索引(以跳過重復的行),而UNION ALL將創建不具有此類索引的表。使用UNION ALL時的性能改進。 UNION會自行刪除所有重復的記錄,因此無需使用DISTINCT子句,僅嘗試按子查詢查詢整個結果集中的一個GROUP BY,這也將最小化執行時間,而不是對每個子查詢進行結果分組。

確保在列上添加了正確的索引,尤其是在WHERE,ORDER BY, GROUP BY中使用的列,相對於其中的數據性質,數據類型應該適合於每個列,例如post_posted_date應該是datetime,date與索引也。

這是查詢的基本思路

SELECT q.* FROM (
SELECT * FROM 
vPAS_Posts_Users 
WHERE (post_user_id =:id AND post_type != 4) 
AND post_updated >:updated 

UNION ALL


SELECT vPAS_Posts_Users.* FROM PAS_Follow 
JOIN vPAS_Posts_Users ON 
( PAS_Follow.folw_followed_user_id = vPAS_Posts_Users.post_user_id 
AND vPAS_Posts_Users.post_updated >:updated) 
WHERE (( PAS_Follow.folw_follower_user_id =:id AND PAS_Follow.folw_deleted = 0 ) 
OR ( post_type = 4 AND post_passed_on_by = PAS_Follow.folw_follower_user_id 
AND post_user_id !=:id )) 

) q
GROUP BY q.post_post_id ORDER BY q.post_posted_date DESC LIMIT :limit

參考

Union與Union All之間的差異–最佳性能比較

優化Mysql聯合

MySQL性能博客

從您的解釋中,我可以看到您的大多數表除了主鍵外沒有其他鍵,我建議您在要連接的列上添加一些額外的鍵,例如:PAS_Follow.folw_followed_user_id和vPAS_Posts_Users.post_user_id,僅此將大大提高性能。

再見Gnagno

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM