1

我有以下查询...</p>

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 运行查询,结果如下

EXPLAIN 查询结果

********编辑**********查看定义

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`)));
4

3 回答 3

1

试试这个查询:

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- 提取另一个解释计划,以便我们调整查询。


解释结果

解释结果

于 2013-08-13T16:51:53.027 回答
1

以下是查询和查看的一些建议,首先使用UNION两个结果集,这可能会使您的查询工作缓慢,而不是您可以使用UNION ALL

为什么我要你使用 UNION ALL

原因是两者都UNION ALL使用UNION 临时表来生成结果。执行速度的差异来自于UNION需要内部临时表带索引(跳过重复行)而UNION ALL将创建没有此类索引的表。这解释了使用时性能略有提高UNION ALLUNION它自己将删除任何重复记录,因此无需使用该DISTINCT子句,尝试仅通过子查询对整个结果集进行一个 GROUP BY 这也将最小化执行时间,而不是在每个子查询中对结果进行分组。

确保您在列上添加了正确的索引,特别是在 中使用的列WHERE,ORDER BY, GROUP BY,数据类型应该适合每一列,就其数据的性质而言,post_posted_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 Union

MySQL 性能博客

于 2013-08-13T22:19:28.690 回答
0

从您的解释中,我可以看到您的大多数表除了主表之外没有任何键,我建议您在要加入的列上添加一些额外的键,例如:PAS_Follow.folw_followed_user_id 和vPAS_Posts_Users.post_user_id,这将导致性能大幅提升。

再见,格纳尼奥

于 2013-08-13T19:59:18.960 回答