SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 11.09.2008 12:56:43

siteres
Участник
Зарегистрирован: 11.09.2008
Сообщений: 1

Долгие запросы без JOIN, но с 2-мя и более условиями в WHERE

Проблема: очень долго выполняются определенные запросы (без JOIN-ов! но с 2 и более условиями).
Почему так, и как сделать чтобы быстро выполнялись?

Структура кластера:
- 2 сервера с data node (типы таблиц NDB 5.125)
- 2 сервера с sql node (версия MySQL 5.1),
- 1 сервер с management node

Конфигурация всех 5 серверов такая:
- Core 2 Quad, 8Gb RAM, 160GB 10000Rpm

Общий объём базы: 500 Мб
Общее количество таблиц: 31

1. Вот такой запрос тормозит (выполняется от 6 до 20 секунд):

Код:

SELECT SQL_CALC_FOUND_ROWS `user`.* FROM `user` 
WHERE (user_is_hidden IS NULL) 
AND (user_not_activated IS NULL) 
AND (user_inserted > '2008-09-02 15:00:05') 
AND (user_rate < 500) 
AND ((user_sex = 'm' ) 
AND ((user_age >= '21' AND user_age <= '25')) 
AND (user_city_id = '1' ) 
AND (user_country_id = '1' ) 
AND (user_collages > 0) 
AND (user_last_visit > '2008-09-04 00:00:00')) 
ORDER BY `user`.`user_id` DESC 
LIMIT 127

вот структура таблицы:
(Количество записей - около 100 000 (размер таблицы 13 Мб))

Код:

CREATE TABLE `user` (
  `user_id` int(10) unsigned NOT NULL auto_increment,
  `user_name` varchar(255) default NULL,
  `user_phone` varchar(255) default NULL,
  `user_sex` char(2) default NULL,
  `user_foto_ext` varchar(255) default NULL,
  `user_clicks` int(11) default NULL,
  `user_clicks_last_ip` varchar(20) default NULL,
  `user_inserted` datetime default NULL,
  `user_updated` timestamp NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `user_last_visit` datetime default NULL,
  `user_is_premium` int(1) default NULL,
  `user_is_premium_from` datetime default NULL,
  `user_email` varchar(255) default NULL,
  `user_password` varchar(255) default NULL,
  `user_ip` varchar(22) default NULL,
  `user_cookie_id` varchar(32) default NULL,
  `user_id_from` int(11) default NULL,
  `user_id_group` int(11) default NULL,
  `user_age` int(11) default NULL,
  `user_birthday` date default NULL,
  `user_about` text,
  `user_city` varchar(255) default NULL,
  `user_country_id` smallint(5) unsigned default NULL,
  `user_city_id` int(10) unsigned default NULL,
  `user_auto_location` tinyint(1) default NULL,
  `user_last_mail` datetime default NULL,
  `user_sended_invites` int(11) default NULL,
  `user_rate` int(11) default NULL,
  `user_top` datetime default NULL,
  `user_is_hidden` tinyint(3) unsigned default NULL,
  `user_nospam` varchar(20) default NULL,
  `user_is_moder` tinyint(3) default NULL,
  `user_source` varchar(20) default NULL,
  `user_source_result` varchar(20) default NULL,
  `user_not_activated` tinyint(1) default NULL,
  `user_last_notify` datetime default NULL,
  `user_rotated` datetime default NULL,
  `user_ref_id` int(10) unsigned default NULL,
  `user_deviz` varchar(70) default NULL,
  `user_collages` smallint(5) unsigned default NULL,
  `user_why` text,
  `user_galleries` smallint(5) unsigned default NULL,
  PRIMARY KEY  (`user_id`),
  KEY `i_cid` (`user_cookie_id`),
  KEY `i_user_from` (`user_id_from`),
  KEY `i_email` (`user_email`),
  KEY `i_us` (`user_source`),
  KEY `i_mixed` (`user_inserted`,`user_rate`,`user_is_hidden`,`user_not_activated`),
  KEY `i_rotate` (`user_is_hidden`,`user_sex`,`user_age`),
  KEY `i_name` (`user_name`),
  KEY `i_ccid` (`user_country_id`,`user_city_id`),
  KEY `i_collage` (`user_collages`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

-------

2. И вот такой (от 1 до 3 секунд) :

Код:

SELECT `game_user`.* FROM `game_user` WHERE ((gu_from_user_id = '51124' OR gu_to_user_id = '51124'))

стурктура таблицы:
(Количество записей - тоже около 100 000 (размер 5 Мб.))

Код:

CREATE TABLE `game_user` (
  `gu_id` int(11) unsigned NOT NULL auto_increment,
  `game_id` int(11) default NULL,
  `gu_from_user_id` int(11) default NULL,
  `gu_from_user_sex` char(3) default NULL,
  `gu_to_user_id` int(11) default NULL,
  `gu_to_user_sex` char(3) default NULL,
  `gu_started` datetime default NULL,
  `gu_closed` datetime default NULL,
  `gu_status` varchar(20) default NULL,
  `gu_last_message_w` tinyint(4) default NULL,
  `gu_last_message_m` tinyint(4) default NULL,
  PRIMARY KEY  (`gu_id`),
  KEY `ddddfff` (`gu_from_user_id`,`gu_from_user_sex`,`gu_last_message_w`),
  KEY `ffffdddd` (`gu_from_user_id`,`gu_from_user_sex`,`gu_last_message_m`),
  KEY `ffhbfrty` (`gu_from_user_id`,`gu_to_user_id`),
  KEY `xxx` (`game_id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

На обычном mysql эти запросы выполняются в 0.05 секунд самое долгое.

Скажите, это нормальная ситуация?
Как её можно решить?????? Всем заранее благодарен за помощь

Неактивен

 

#2 11.09.2008 14:26:53

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Долгие запросы без JOIN, но с 2-мя и более условиями в WHERE

Проблема в том, что у Вас используется кластер. Для того, чтобы получить данные
по запросу, не использующему индекс, в случае дисковой таблицы 13 мегабайт - Вам
нужно потратить несколько миллисекунд для вытаскивания всей таблицы. В то же время,
вытаскивание всех строк с кластера - это очень неблагодарный процесс (т.к. данные
нужно притащить со всех датанод на SQL-ноду и на ней выкинуть ненужные).

Кластер будет оптимально работать в случае, когда Вы будете делать точечные запросы
по данным (т.е. во втором случае, подозреваю, что хватит добавления ключа на gu_to_user_id),
в этом случае условия будут проталкиваться на датаноды, и оттуда будут забираться
только нужные строки.

Для первого запроса я бы попробовал ключ на user_age / user_last_visit в зависимости от
селективности, хотя я не уверен, что range-запросы протолкнутся на датаноды.

P.S. У нас есть специалист по кластеру, возможно, он ответит более полно.

Неактивен

 

#3 11.09.2008 14:37:12

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Долгие запросы без JOIN, но с 2-мя и более условиями в WHERE

Есть определенные условия, при которых WHERE обрабатывается на дата-нодах, не требуя вытаскивания всей таблицы на SQL-ноду. Механизм описан в документации: http://dev.mysql.com/doc/refman/5.0/en/ … ation.html

На практике.
1. убедитесь, что переменная engine_condition_pushdown=1
2. Сделайте EXPLAIN запросу и убедитесь, что в комментариях присутствует упоминание "condition pushdown"

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson