SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

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

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

Вы не зашли.

#1 07.03.2012 09:18:31

CaypoG
Участник
Зарегистрирован: 07.03.2012
Сообщений: 3

Черезчур медленный запрос...

Здравствуйте.

Задача у меня была такая: есть 2 таблицы с данными по звонкам (кто, куда, время и т.д.). Нужно сравнивать их раз в сутки, и смотреть какие звонки есть в таблице №1 но не попали в таблицу №2 и наоборот, есть в №2 но нет в №1.

Исходные данные у меня такие:


--
-- Структура таблицы `tmp`
--

CREATE TABLE IF NOT EXISTS `tmp` (
  `id` bigint(13) NOT NULL AUTO_INCREMENT,
  `caller` bigint(11) DEFAULT NULL,
  `called` bigint(16) DEFAULT NULL,
  `datetime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=323810 ;


--
-- Структура таблицы `test`
--

CREATE TABLE IF NOT EXISTS `test` (
  `callerid` bigint(11) DEFAULT NULL,
  `dnid` bigint(16) DEFAULT NULL,
  `channel` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  `dstchannel` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  `begintime` datetime DEFAULT NULL,
  `answtime` datetime DEFAULT NULL,
  `endtime` datetime DEFAULT NULL,
  `duration` int(11) DEFAULT NULL,
  `reason` varchar(15) COLLATE utf8_bin DEFAULT NULL,
  `reason_code` int(2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
 


Я решил сделать это следующим образом:
SELECT * FROM `test` LEFT JOIN `tmp` ON `begintime` = `datetime` WHERE ISNULL(tmp.id) AND `begintime` >= '2012-03-06' AND `begintime` < '2012-03-07'


Запрос обрабатывается примерно за 10 секунд.

А вот обратный
SELECT * FROM `tmp` LEFT JOIN `test` ON `datetime` = `begintime` WHERE ISNULL(tmp.id) AND `datetime` >= '2012-03-06' AND `datetime` < '2012-03-07'


И вот он уже выполняется очень очень долго. Попробовал делать выборку не за весь день, а за одни час. Так вот запрос на один час выполняется за 43 секунды.

Explain extended:
id    select_type    table    type    possible_keys    key    key_len    ref    rows    filtered    Extra
1    SIMPLE    tmp    ALL    NULL    NULL    NULL    NULL    12600    100.00    Using where
1    SIMPLE    test    ALL    NULL    NULL    NULL    NULL    13882    100.00    Using where

Подскажите, пожалуйста, что здесь нужно оптимизировать, либо вообще поменять?

Спасибо.

Отредактированно CaypoG (07.03.2012 09:30:47)

Неактивен

 

#2 07.03.2012 10:19:37

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Черезчур медленный запрос...

А какая у вас версия?
Второй запрос должен отработать мгновенно и вернуть пустой результат, а explain написать Impossible WHERE. Или вы приводите здесь не тот запрос, который выполняете на самом деле.

Кроме того смущает идентификация звонков только по времени. А если было несколько звонков в одно время? Или такая ситуация не возможна?

Ну и конечно индексов у вас нет никаких, даже на время.

Неактивен

 

#3 07.03.2012 11:00:49

CaypoG
Участник
Зарегистрирован: 07.03.2012
Сообщений: 3

Re: Черезчур медленный запрос...

vasya написал:

А какая у вас версия?

5.1.41

vasya написал:

Второй запрос должен отработать мгновенно и вернуть пустой результат, а explain написать Impossible WHERE. Или вы приводите здесь не тот запрос, который выполняете на самом деле.

Да, прошу прощения, просто скопировал не до конца поправив. Второй запрос на самом деле такой:

SELECT * FROM `tmp` LEFT JOIN `test` ON `datetime` = `begintime` WHERE ISNULL(test.callerid) AND `datetime` >= '2012-03-06' AND `datetime` < '2012-03-07'

vasya написал:

Кроме того смущает идентификация звонков только по времени. А если было несколько звонков в одно время? Или такая ситуация не возможна?

Возможна, но не на тестовом сервере. Отбор только по времени для того, чтобы сократить время выполнения запроса, которое и так огромное. А в целом да, ещё нужно смотреть по АНИ звонившего, и набранному номеру.

vasya написал:

Ну и конечно индексов у вас нет никаких, даже на время.

Проиндексировал datetime и begintime. Выполнилось за 0.1994 секунды smile
Дело в том, что tmp табличка каждый день обновляется, а старая информация из неё вытирается. Один раз выставив индекс я проблему решу, или нужно каждый день его проставлять?

Отредактированно CaypoG (07.03.2012 11:07:23)

Неактивен

 

#4 07.03.2012 11:04:48

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Черезчур медленный запрос...

alter table `test` add index(`begintime`);
alter table `tmp` add index(`datetime`);

Неактивен

 

#5 07.03.2012 11:07:51

CaypoG
Участник
Зарегистрирован: 07.03.2012
Сообщений: 3

Re: Черезчур медленный запрос...

Видимо мы с вами одновременно писали. Я редактировал, а вы сообщение добавили smile

Неактивен

 

#6 07.03.2012 11:14:17

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Черезчур медленный запрос...

Индекс добавляется один раз, далее при добавлении/удалении/редактировании данных он автоматически перестраивается.

Неактивен

 

Board footer

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