慢查询:这个例子的实用解决方案?

时间:2015-03-10 15:56:11

标签: php mysql phpmyadmin

我刚刚下载了我的慢查询日志 并且经常显示的一个查询是

select * from feedback_to_user
left join user_tb on  feedback_to_user.feedbacker_id = user_tb.user_id
left join user_to_photo on  feedback_to_user.feedbacker_id = user_to_photo.user_id
where  feedback_to_user.feedbackee_id="7375"    
AND user_tb.admin_review = "1"  
AND user_tb.user_published = "1"    
AND user_tb.user_active = "1"        
AND user_tb.user_verified = "1"             
order by  feedback_to_user.ftu_id DESC;

所以我该如何解决?语法还是phpmyadmin?

2 个答案:

答案 0 :(得分:1)

正如帕特里克已经建议的那样,你应该使用EXPLAIN。

但一般来说,您应该考虑这些要点(在查询检查顺序中):

  

从feedback_to_user选择* ...

是否真的有必要选择带有星号的所有字段?也许您只需要几个。让巨大的数据块肆无忌惮地被忽略和/或丢弃,这一点毫无意义;最好不要在第一时间选择它们。此外,这样MySQL将更好地估计实际的检索成本,并且可能更好地优化查询(稍后参见覆盖索引)。

  

在feedback_to_user.feedbacker_id = user_tb.user_id

上左连接user_tb

你是否希望不能成为feedbacker_id中的任何用户,以便该行将所有user_tb字段设置为NULL,并且您是否还需要该行?如果不是,则使用直接JOIN(不是LEFT JOIN)。改进可能是微不足道的 - 但它们仍然是免费的(出于同样的原因,如果您有疑问,那么请留下LEFT JOIN)。

  

在feedback_to_user.feedbacker_id = user_to_photo.user_id

上左加入user_to_photo

与上述相同。你只需要的照片吗?如果是这样,请加入。

  

其中feedback_to_user.feedbackee_id =" 7375"
  AND user_tb.admin_review =" 1"
  AND user_tb.user_published =" 1"
  AND user_tb.user_active =" 1"
  AND user_tb.user_verified =" 1"

所有这些字段 VARCHAR 还是整数?如果只在那里存储整数(偶尔会出现NULL),那么拥有一个整数数据字段会产生很好的红利。如果你将它们用作旗帜,那么TINYINT可能(并且可能不会)进一步提高性能。也可以调查位域。

但是,如果您有很多这些问题,那么您可以使用您要查询的字段在user_tb上创建一个INDEX:

CREATE INDEX user_db_flags 
ON user_tb(admin_review, 
           user_published,
           user_active,
           user_verified);

您可以尝试添加您在JOIN中使用的user_id字段:

-- remove previous index
ALTER TABLE user_tb DROP INDEX user_db_flags;

-- add index
CREATE INDEX user_db_flags 
ON user_tb(user_id,
           admin_review, 
           user_published,
           user_active,
           user_verified);

有关feedback_to_user的指数:

CREATE INDEX feedback_to_user_id 
        ON feedback_to_user(feedbacker_id, feedbackee_id, ftu_id);

您也可以尝试交换这些职位:

CREATE INDEX feedback_to_user_id 
        ON feedback_to_user(feedbackee_id, feedbacker_id, ftu_id);

这将有助于MySQL摆脱冗余信息并快速找到您需要的信息。

如果其中一个JOINed表只有非常少的非常小的字段,并且选择非常精确(例如feedback_to_user就是你选择单个feedbackee_id的情况),你可以使用&#34 ;覆盖索引",即包含您在第一个位置搜索的字段的索引,以及您在下一个位置需要的字段。特别是如果表有许多其他更大的字段,这允许MySQL在索引上查询而根本不加载表。如果索引足够小于表,则速度增益可能很大。否则,不要打扰 - 维护索引也会产生费用。

答案 1 :(得分:0)

请使用EXPLAIN进行分析,请参阅:

http://dev.mysql.com/doc/refman/5.7/en/using-explain.html

不幸的是我们不知道你的表格结构的行数和索引,但你应该从优化开始阅读:

http://dev.mysql.com/doc/refman/5.7/en/select-optimization.html