Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何优化这个繁重的MySQL查询?_Mysql - Fatal编程技术网

如何优化这个繁重的MySQL查询?

如何优化这个繁重的MySQL查询?,mysql,Mysql,我需要优化一个MySQL查询,这需要很多时间来加载 这是: SELECT p.id, UNIX_TIMESTAMP(p.last_answer_date) AS last_answer_date_timestamp, p.sender_id, p.recipient_id, p.is_read_sender, p.last_answer_user_id, p.is_read_recipient, (SELECT m.read FROM pm_message m WHERE m.conv_i

我需要优化一个MySQL查询,这需要很多时间来加载

这是:

SELECT 
p.id, 
UNIX_TIMESTAMP(p.last_answer_date) AS last_answer_date_timestamp, 
p.sender_id,
p.recipient_id,
p.is_read_sender,
p.last_answer_user_id,
p.is_read_recipient,
(SELECT m.read FROM pm_message m WHERE m.conv_id = p.id AND m.user_id != $user_id ORDER BY m.date DESC LIMIT 1) AS read_status,
(SELECT m.content FROM pm_message m WHERE m.conv_id = p.id ORDER BY m.date DESC LIMIT 1) AS last_message,
(SELECT u.username FROM user u WHERE (u.id = p.sender_id OR u.id = p.recipient_id) AND u.id != $user_id LIMIT 1) AS from_username,
(SELECT u.id FROM user u WHERE (u.id = p.sender_id OR u.id = p.recipient_id) AND u.id != $user_id LIMIT 1) AS from_userid,
(SELECT ui.gender FROM user_info ui WHERE (ui.user_id = p.sender_id OR ui.user_id = p.recipient_id) AND ui.user_id != $user_id LIMIT 1) AS from_gender,
(SELECT ph.thumb_url FROM photo ph, user_info ui WHERE ui.main_photo = ph.id AND (ph.user_id = p.sender_id OR ph.user_id = p.recipient_id) AND ph.user_id != $user_id LIMIT 1) AS from_thumb_url 
FROM pm_conv p
WHERE p.sender_id = $user_id OR p.recipient_id = $user_id
ORDER BY p.last_answer_date DESC LIMIT 25;
这个查询得到了我想要的结果,但它真的很慢。。。我认为嵌套选择是这个查询如此缓慢的原因

以下是此查询的表结构:

CREATE TABLE IF NOT EXISTS `photo` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `url` varchar(255) DEFAULT NULL,
  `thumb_url` varchar(255) DEFAULT NULL,
  `user_id` int(11) NOT NULL,
  `date` datetime NOT NULL,
  `status` int(11) NOT NULL,
  `votes` int(11) DEFAULT '0',
  `comments` int(11) DEFAULT '0',
  `views` int(11) DEFAULT '0',
  `text` text,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE IF NOT EXISTS `pm_conv` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date` datetime NOT NULL,
  `sender_id` int(11) NOT NULL,
  `recipient_id` int(11) NOT NULL,
  `last_answer_date` datetime NOT NULL,
  `nb_messages` int(11) NOT NULL,
  `is_read_sender` int(11) NOT NULL,
  `is_read_recipient` int(11) NOT NULL DEFAULT '0',
  `last_answer_user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `recipient_id` (`recipient_id`),
  KEY `sender_id` (`sender_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE IF NOT EXISTS `pm_message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date` datetime NOT NULL,
  `content` text NOT NULL,
  `user_id` int(11) NOT NULL,
  `conv_id` int(11) NOT NULL,
  `read` int(11) DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `conv_id` (`conv_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `encrypt_id` varchar(255) DEFAULT NULL,
  `register_date` datetime DEFAULT NULL,
  `last_login_date` datetime DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `banned` int(11) DEFAULT NULL,
  `banned_reason` text,
  `first_step_form` int(11) DEFAULT '0',
  `status` int(11) DEFAULT NULL,
  `valid_snapchat` int(11) DEFAULT '0',
  `introduced_forum` int(11) DEFAULT '0',
  `referer` varchar(255) DEFAULT NULL,
  `allow_social_featuring` int(11) DEFAULT NULL,
  `rank` int(11) DEFAULT NULL,
  `fb_id` bigint(20) DEFAULT NULL,
  `rate_app_status` int(11) DEFAULT NULL,
  `last_activity_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE IF NOT EXISTS `user_info` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `gender` int(11) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `about` text,
  `main_photo` int(11) DEFAULT NULL,
  `country` varchar(100) DEFAULT NULL,
  `city` varchar(100) DEFAULT NULL,
  `relation_type` varchar(30) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `fb_link` varchar(255) DEFAULT NULL,
  `twitter_link` varchar(255) DEFAULT NULL,
  `youtube_link` varchar(255) DEFAULT NULL,
  `instagram_link` varchar(255) DEFAULT NULL,
  `app_pref_forum` int(11) DEFAULT NULL,
  `app_pref_pm` int(11) DEFAULT NULL,
  `app_pref_snapchat_request` int(11) DEFAULT NULL,
  `browse_invisibly` int(11) DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `main_photo` (`main_photo`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
有人能帮我优化这个繁重的查询吗


谢谢

您可以在解释计划中看到一些表被低效的索引访问。尝试计算所有表的统计信息,看看它是否改变了什么(使用分析表)。

您可以加入
user
表,以便一次获取用户名和id,而不是有两个子查询,您可能可以对
pm\u message
执行相同的操作,但由于子查询具有不同的条件,所以这有点棘手。
我也会将
user
user\u info
表组合成一对一的关系,因此将这些数据存储在不同的表中是没有意义的。这将允许您摆脱第4个子查询并简化第5个子查询。

在某些情况下,最好执行多个查询,而不是一个子查询。

那么EXPLAIN有什么要说的呢?EXPLAIN告诉我:好的。获取MySQL工作台并将其用于解释,因为它提供了执行计划的图形解释,更易于理解,也更易于测试解决方案。然后,您可以看到在a)每次删除一个子查询并测量每个查询的影响时发生的情况。b) 尝试不同的查询构造。逐个删除嵌套的选择,以确定哪些是导致性能问题的原因。然后关注这些。