2015-03-16 3 views
0

Мне нужно оптимизировать 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_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 ; 

Может кто-то помочь мне, чтобы оптимизировать этот тяжелый запрос?

Спасибо!

+0

Так что сказать EXPLAIN? –

+0

Вот что говорит мне EXPLAIN: http://i.stack.imgur.com/ht6WX.png – fraxool

+0

ОК. Получите Workbench MySQL и используйте это для своего объяснения, потому что он дает графическую интерпретацию плана выполнения, который намного легче понять и гораздо проще тестировать решения. http://www.mysql.com/products/workbench/. Затем вы можете видеть, что происходит, когда вы: а) удаляете каждый подзапрос по одному за раз и оцениваете влияние каждого из них. б) попробуйте различные конструкции запросов. –

ответ

0

вы можете увидеть в плане объяснения, к которым обращаются некоторые таблицы неэффективными индексами. попробуйте рассчитать статистику по всем таблицам, чтобы увидеть, что она что-то меняет (используя таблицу анализа).

0

Вы можете присоединиться к таблице user, чтобы сразу получить имя пользователя и идентификатор вместо двух подзапросов, возможно, вы можете сделать то же самое с pm_message, но это немного сложнее, поскольку подзапросы имеют разные условия.
Я бы также объединил таблицы user и user_info, так как я вижу, что они имеют отношение «один к одному», поэтому хранить эти данные в разных таблицах бессмысленно. Это позволит вам избавиться от 4-го подзапроса и упростить пятый.
В некоторых случаях лучше выполнить несколько запросов вместо одного с подзапросами.

Смежные вопросы