SELECT ... FROM tbl WHERE x in(SELECT x FROM tbl ...) виснет наглухо

gena_s

Новичок
SELECT ... FROM tbl WHERE x in(SELECT x FROM tbl ...) виснет наглухо

Есть такой образный запрос, при котором mysqld выжерает все ресурсы и дождаться результата нет сил.
SELECT ... FROM tbl WHERE x in(SELECT x FROM tbl ...)

Хотя:

(SELECT x FROM tbl ...) - выдает всего 12 значений. Выполняется за 7 сек.

а,

SELECT ... FROM tbl WHERE x in(...12 значений вбиваем ручками...) выдает 532 значения тоже за 7 сек.

Чего-ж все вместе так тормозит-то???
 

Фанат

oncle terrible
Команда форума
не джолжно бы 12 секунд делать.
а сколько всего записей в таблице-то?
 

zerkms

TDD infected
Команда форума
ну и дополняя фаната - почему не INNER JOIN?
 

gena_s

Новичок
>а что мешает сделать два запроса?

Ничего, а хочется одним

>а сколько всего записей в таблице-то?

SELECT COUNT(*) FROM tbl

4019654 :)

>почему не INNER JOIN

Сейчас гляну что это такое

угу глянул - Таблица у меня одна :D
 

Фанат

oncle terrible
Команда форума
при чем здесь джойн или количество запросов? сначала надо сделать, чтобы запрос выполнялся не 12, а 0,0012 секунды.
после этого уже разговаривать обо всем остальном
 

zerkms

TDD infected
Команда форума
*****
я же сказал "дополняя". это слово подразумевает, что мой совет должен быть принят к сведению после твоего :)

gena_s
показывай запрос в том виде, в котором он есть, без упрощений
и схему таблицы (которая SHOW CREATE TABLE)
 

gena_s

Новичок
Ну ладно пазорица так пазорица, сильно не ругайте (какбудто маме дневник с двойками даю)

Вот запрос, который хочу:
SELECT calldate,userfield,billsec,duration FROM cdr WHERE dst in(
SELECT dst FROM cdr
WHERE dst>99999 and calldate>'2009-01-01' and calldate<'2009-05-01' and substring(userfield,8,4)='1123' and billsec>30
Group by dst
Having COUNT(DISTINCT(substring(userfield,1,6)))>1
order by dst)

Вот как создавали таблицу: (кто знает это с ASTERISK-а)
CREATE TABLE `cdr` (
`calldate` datetime NOT NULL default '0000-00-00 00:00:00',
`clid` varchar(80) NOT NULL default '',
`src` varchar(80) NOT NULL default '',
`dst` varchar(80) NOT NULL default '',
`dcontext` varchar(80) NOT NULL default '',
`channel` varchar(80) NOT NULL default '',
`dstchannel` varchar(80) NOT NULL default '',
`lastapp` varchar(80) NOT NULL default '',
`lastdata` varchar(80) NOT NULL default '',
`duration` int(11) NOT NULL default '0',
`billsec` int(11) NOT NULL default '0',
`disposition` varchar(45) NOT NULL default '',
`amaflags` int(11) NOT NULL default '0',
`accountcode` varchar(20) NOT NULL default '',
`uniqueid` varchar(32) NOT NULL default '',
`userfield` varchar(255) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
 

zerkms

TDD infected
Команда форума
calldate <--- на это поле индекс поставь, потом измерь время выполнения внутреннего запроса и покажи EXPLAIN для него же
по поводу остального - полное ояебу %)
 

zerkms

TDD infected
Команда форума
*****
кстати, поможет :) индекс клёво отсечёт от 4М записей выборку, например, в несколько тысяч, над которой, может даже в памяти, произведёт остальные ояебу вычисления.
 

Фанат

oncle terrible
Команда форума
ну может быть, да. хотя мы не знаем, сколько у него в этом диапазоне записей. если это биллинг, то может и лимон набежать. и в этом смысле индексы могут затормозить вставку, кстати.

-~{}~ 21.05.09 16:35:

но субстринги из юзерфилда - это жесть
 

zerkms

TDD infected
Команда форума
Вот как создавали таблицу: (кто знает это с ASTERISK-а)
*****
это единственное, что оправдывает ТС :)

по поводу запроса - если что и поможет, то только индекс на дату. потому как на другие поля, подозреваю, вариативность будет просто никакая.

gena_s
сколько у тебя в среднем записей в день добавляется? сколько записей попадёт в вышеуказанный диапазон по датам?
 

gena_s

Новичок
>полное ояебу %
в смысле полный бред?

>но субстринги из юзерфилда - это жесть
а чего там жесткого?

>не знаем, сколько у него в этом диапазоне записей
В этом диапазоне 1070100 записей
как-раз лимон

>если это биллинг
биллинг с нее и делаем

Какой вердикт - пробовать индекс поставь?
 

prolis

Новичок
gena_s
1. в документации ещё и индексы были:
[sql]
ALTER TABLE cdr ADD INDEX ( calldate );
ALTER TABLE cdr ADD INDEX ( dst );
ALTER TABLE cdr ADD INDEX ( uniqueid );
[/sql]
2. dst>99999 (WTF? - может это звонки на внешние номера, более 5 символов?)
3.насчет юзерфиелда согласен с предыдущими коллегами, что там?
4.данные за 4 месяца обязательно, месяца не хватит?
5.в зависимости от целей, может подумать о разделении оперативной и аналитической информации (на основе данной таблицы сливать данные в приспособленную таблицу)?
 

gena_s

Новичок
zerkms
>записей в день
12 тыщ

prolis
2. да, так и есть
3. тоже со всеми согласен там 3 поля
4-5. поймать номер телефона который всплывает по разным проектам "substring(userfield,1,6)" а таких может быть всего 2 звонка, один пол года назад, а другой завтра - какая тут аналитика?

с индексами и сабстрингами будем разбираться спасибо
 

Wicked

Новичок
запрос в первом сообщении тормозит из-за correlated subquery

ЗЫ: explain так никто и не покажет? :)
 

prolis

Новичок
gena_s
тогда в лоб:
[sql]
CREATE TABLE `temp` (
`dst` varchar(80) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

insert into temp (dst)
SELECT dst FROM cdr
WHERE calldate between '2009-01-01' and '2009-05-01'
and substring(userfield,8,4)='1123'
and billsec>30
and LENGTH(dst)>5
Group by dst
Having COUNT(DISTINCT(substring(userfield,1,6)))>1;

ALTER TABLE temp ADD INDEX ( dst ) ;

SELECT calldate,userfield,billsec,duration FROM cdr,temp WHERE cdr.dst=temp.dst;

drop table temp;
[/sql]
 

gena_s

Новичок
интересно было почитать про explain спасибо.

explain + ояебучий запрос - висим. :(

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

Всем кто помогал спасибо.
 
Сверху