Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.06.27;
Скачать: [xml.tar.bz2];

Вниз

Оптимизация запроса   Найти похожие ветки 

 
Andrey   (2004-05-31 10:13) [0]

Проблема в следующем: при попытке выполнить запрос к таблице, состоящей из 6,000,000 записей, комп выполняет его где-то секунд 30. Открытие той же таблицы через TTable (с установленным индексом) происходит почти сразу (через пару секунд). Отсюда и вопрос, что делать? (без запроса не обойтись)


 
mutabor   (2004-05-31 10:15) [1]

база какая?


 
Vlad ©   (2004-05-31 10:16) [2]


> Andrey   (31.05.04 10:13)  

Приведи запрос


 
Andrey   (2004-05-31 10:17) [3]

Написано же в заголовке: D6, MySQL. Версию MySQL не знаю, но одна из последних


 
Andrey   (2004-05-31 10:17) [4]

select * from contract,client,fund
where contract.fundid=fund.fundid and contract.clt_auto=client.clt_auto
and (contract.ctp_auto=6478102 or contract.ctp_auto=684954 or contract.ctp_auto=409368)


 
Полный дурак   (2004-05-31 10:17) [5]


> Написано же в заголовке: D6, MySQL. Версию MySQL не знаю,
> но одна из последних


Это что, - запрос что-ли?


 
Andrey   (2004-05-31 10:21) [6]

Ну так что, есть какие-то варианты?


 
Vlad ©   (2004-05-31 10:23) [7]


> Andrey   (31.05.04 10:17) [4]

Индексы по всем полям cвязки есть ?
и еще, возможно or тормозит запрос, попробуй оставить только contract.ctp_auto=6478102, остальное убрать (ради эксперимента)


 
Sergey13 ©   (2004-05-31 10:25) [8]

2Andrey   (31.05.04 10:17) [4]
Индексы есть?


 
DenK_vrtz ©   (2004-05-31 10:27) [9]

при выборе поля всех трех таблиц нужны (SELECT * ...)?


 
Andrey   (2004-05-31 10:29) [10]

Индексы есть по всем полям.

Запрос модифицировал:

select * from contract,client,fund
where contract.fundid=fund.fundid and contract.clt_auto=client.clt_auto
and (contract.ctp_auto IN (6478102,684954,409368));

Тормозит все равно.

А когда в Table ставлю Filter=ctp_auto=6478102 or и т.д. , нормально работает!


 
Vlad ©   (2004-05-31 10:32) [11]


> Andrey   (31.05.04 10:29) [10]

Я же сказал, попробуй оставить только одно значение contract.ctp_auto = 6478102 без всяких OR или IN (что одно и тоже)


 
DenK_vrtz ©   (2004-05-31 10:32) [12]

СТОП.
Так результирующий курсор будет иметь ограничения по 3-м условиям?
исходя из - (contract.ctp_auto=6478102 or contract.ctp_auto=684954 or contract.ctp_auto=409368)

Если так, то сначала ограничь набор contract, а потом сделай объединение с client,fund.


 
Andrey   (2004-05-31 10:32) [13]

Еще особенность: в таблице contract примерно 15 полей, в таблице client около 30. Нужны в запросе почти все


 
sniknik ©   (2004-05-31 10:34) [14]

не надо вводить в заблуждение (это мягко говоря)
вот это
select * from contract,client,fund
....
TTable не откроет ни через пару секунд ни вообще, запрос с обьеденением трех таблиц всегда медленнее чем выборка из одной (случай с TTable), поборотся за скорость конечно можно но это другая песня.
к примеру я бы (хотя я не работаю с MySQL) поставил бы условия с явным сравнением на первое место, на случай если MySQL выполняет условия поочередно, а обьеденение потом.


 
Andrey   (2004-05-31 10:34) [15]

"СТОП.
Так результирующий курсор будет иметь ограничения по 3-м условиям?
исходя из - (contract.ctp_auto=6478102 or contract.ctp_auto=684954 or contract.ctp_auto=409368)

Если так, то сначала ограничь набор contract, а потом сделай объединение с client,fund."

А ты примерчик не мог бы привести?


 
Andrey   (2004-05-31 10:38) [16]


> не надо вводить в заблуждение (это мягко говоря)
> вот это
> select * from contract,client,fund
> ....
> TTable не откроет ни через пару секунд ни вообще, запрос
> с обьеденением трех таблиц всегда медленнее чем выборка
> из одной (случай с TTable), поборотся за скорость конечно
> можно но это другая песня.

Ну это понятно. Без запроса не обойтись. В TTable я делал lookup-поля, но все равно потом нужен будет другой запрос (во время выполнения исходный запрос изменяется)


 
DenK_vrtz ©   (2004-05-31 10:39) [17]

если нигде не наврал, то так :)

SELECT * FROM
(SELECT * FROM contract WHERE ctp_auto IN (6478102,684954,409368)) contract, client, fund
WHERE contract.fundid=fund.fundid
AND   contract.clt_auto=client.clt_auto


 
Vlad ©   (2004-05-31 10:41) [18]

sniknik ©   (31.05.04 10:34) [14]


> запрос с обьеденением трех таблиц всегда медленнее чем выборка
> из одной (случай с TTable), поборотся за скорость конечно
> можно но это другая песня.

Как показали тесты на IB, при ~6 млн записях практически не заметно, три таблицы там объединяются или одна. Если есть необходимые индексы, то запрос срабатывает пулей.
Но как только в запрос добавляешь OR или IN, это серьезно сказывается на быстродействии.


 
Andrey   (2004-05-31 10:42) [19]


> если нигде не наврал, то так :)
>
> SELECT * FROM
> (SELECT * FROM contract WHERE ctp_auto IN (6478102,684954,409368))
> contract, client, fund
> WHERE contract.fundid=fund.fundid
> AND   contract.clt_auto=client.clt_auto

Блин. По-моему, select из select-a не работает. Но сейчас еще раз проверю


 
Andrey   (2004-05-31 10:46) [20]

Ага. По ctp_auto нету индекса, видимо в этом проблема?


 
Vlad ©   (2004-05-31 10:47) [21]


> Andrey   (31.05.04 10:46) [20]
> Ага. По ctp_auto нету индекса, видимо в этом проблема?

Естественно, индексы д.б. по всем полям, по к-рым происходит отбор.


 
DenK_vrtz ©   (2004-05-31 10:48) [22]

Andrey   (31.05.04 10:46) [20]

Так тебя ж сразу спросили про индексы!!!


 
Sandman25+1   (2004-05-31 10:49) [23]

Индексы по fund.fundid и client.clt_auto есть?


 
sniknik ©   (2004-05-31 10:50) [24]

Vlad ©   (31.05.04 10:41) [18]
т.е. хочеш сказать что декартово обьеденение трех таблиц по 6млн. записей такойже по скорости как открытие одной без обьеденений (как делает табле)?
позволь не поверить
а вот если есть ограничивающеее условие в силу которого вибирается малая часть то тут будет зависеть от того что было вначале обьеденение всего или выборка и последующее обьеденение малой части.
как сработает конкретный движок, вопрос, если есть анализатор запроса пофигу что где ставить. но на всякий случай... и вообще начал бы с тестов и доков что и как в конкретном движке работает (имхо).


 
Andrey   (2004-05-31 10:51) [25]


> Так тебя ж сразу спросили про индексы!!!

Ну, не заметил. Зато поговорили.
Кстати, селект из селекта все-таки не работает. Можно продолжить тему об этом.


 
Andrey   (2004-05-31 10:54) [26]


> Индексы по fund.fundid и client.clt_auto есть?

По ним есть - это первичные ключи


 
DenK_vrtz ©   (2004-05-31 10:57) [27]

Если не работает select из select"a, то SELECT * FROM contract WHERE ctp_auto IN (6478102,684954,409368) можно загнать во view

:) "но это уже совсем другая история"


 
Vlad ©   (2004-05-31 11:01) [28]


> sniknik ©   (31.05.04 10:50) [24]


> т.е. хочеш сказать что декартово обьеденение трех таблиц
> по 6млн. записей такойже по скорости как открытие одной
> без обьеденений (как делает табле)?

Есть основная таблица (6 млн записей) и есть 2 справочника, получаем декартово произведение трех таблиц, затем естественно связываем таблицы по ключевым полям и ограничиваем выборку по нек-му критерию (индексированному полю). Так вот - на глаз никакой разницы нет, что мы выбираем из одной, что из трех таблиц. Результат не заставляет ждать и секунды (Так на IB во всяком случае)


 
Andrey   (2004-05-31 11:04) [29]


> Индексы по fund.fundid и client.clt_auto есть?


Нет индексов по contract.fundid и contract.clt_auto. Может, из-за этого он вешается?


 
Nikolay M. ©   (2004-05-31 11:06) [30]


> Есть основная таблица (6 млн записей) и есть 2 справочника,
> получаем декартово произведение трех таблиц, затем естественно
> связываем таблицы по ключевым полям и ограничиваем выборку
> по нек-му критерию (индексированному полю). Так вот - на
> глаз никакой разницы нет, что мы выбираем из одной, что
> из трех таблиц. Результат не заставляет ждать и секунды
> (Так на IB во всяком случае)

А что, в IB нет оптимизатора запросов, который сам оптимальным образом расставляет порядок условий в WHERE? Даже в мускуле оптимизатор есть.


 
DenK_vrtz ©   (2004-05-31 11:06) [31]

Andrey   (31.05.04 11:04) [29]

в ромашку играем? Пробуй!


 
Andrey   (2004-05-31 11:07) [32]


> Есть основная таблица (6 млн записей) и есть 2 справочника,
> получаем декартово произведение трех таблиц, затем естественно
> связываем таблицы по ключевым полям и ограничиваем выборку
> по нек-му критерию (индексированному полю). Так вот - на
> глаз никакой разницы нет, что мы выбираем из одной, что
> из трех таблиц. Результат не заставляет ждать и секунды
> (Так на IB во всяком случае)

Хе. Не совсем. Я сейчас убрал условие по ctp_auto и он один хрен тормозит.


 
Vlad ©   (2004-05-31 11:12) [33]


> Andrey   (31.05.04 11:07) [32]


> Я сейчас убрал условие по ctp_auto

Да не надо совсем его убирать. Естественно будет тормозить, ты же выбираешь теперь произведение всех записей !
Говорю, сделай индекс по этому полю, и ограничивай без всяких OR или IN то есть просто ctp_auto = XXX


 
sniknik ©   (2004-05-31 11:13) [34]

Vlad ©   (31.05.04 11:01) [28]
вот!
> и ограничиваем выборку по нек-му критерию (индексированному полю).
это на твой взгляд делается после, на самом деле движок обычно сначала ограничивает, а обьеденение уже по 100записям к примеру (что в выборку вошло) делает, это большого времени не составляет,
убери условие ограничения (чтобы получить полное декартово произведение таблиц) и посмотри сколько времени займет.

> Нет индексов по contract.fundid и contract.clt_auto. Может, из-за этого он вешается?
одна из причин. для присоеденения по неиндексированному полу обычно строится временный индекс.


 
sniknik ©   (2004-05-31 11:16) [35]

полу = полю
;)
впрочем к какому нибудь неиндексированному(и противоположному) полу я бы тоже присоеденился... ;о))


 
Vlad ©   (2004-05-31 11:20) [36]


> sniknik ©   (31.05.04 11:13) [34]

а я разве с этим спорю, это делает оптимизатор практически во всех СУБД.
Речь о том, что если в ограничивающее условие впихнуть OR то будут заметные тормоза.


 
Andrey   (2004-05-31 11:26) [37]

Ну а как без OR обойтись?

Надо ограничивать по всем трем значениям!


 
Vlad ©   (2004-05-31 11:28) [38]


> Andrey   (31.05.04 11:26) [37]

Ты попробуй сначала, просто ради эксперимента. Может не в этом дело, тогда дальше думать будем. Нужно же локализовать проблему


 
sniknik ©   (2004-05-31 11:31) [39]

может оптимизатор с OR не справляется? на access/MSSQL такого не замечал.


 
Andrey   (2004-05-31 11:32) [40]

Да я попробовал - один хер не пашет.

Может, MySQL плохо делает декартово произведение или вообще тупит при работе с большими таблицами?


 
Vlad ©   (2004-05-31 11:33) [41]


> sniknik ©   (31.05.04 11:31) [39]

На небольших объемах (100-200 тыс) это не заметно, зато начинает здорово сказываться  при объеме свыше 1 млн.
Тоже самое относится и к between - также серьезно затормаживает выборку, причем никакие индексы не спасают


 
sniknik ©   (2004-05-31 11:35) [42]

еше попробуй делять явное присоеденение (INNER JOIN)
и индексы обязательно сделай.


 
Vlad ©   (2004-05-31 11:35) [43]


> Andrey   (31.05.04 11:32) [40]
> Да я попробовал - один <censored> не пашет.

Значит однозначно дело в индексах.
То есть у тебя не хватает индекса(ов) по каким-то полям используемым в where


 
Andrey   (2004-05-31 11:38) [44]

Блин, похоже, совсем беда.

Удалил данные (заново импортировал за неделю). Теперь в contract примерно 10000 записей, в client - около 4000. Не пашет. Не может же такого быть! Запрос ведь примитивный совсем.


 
Andrey   (2004-05-31 11:45) [45]

Ладно, идем другим путем. Делаю через Table, добавил lookup-поля из client и contract. В Filter написал ctp_auto= or ...

Далее, во время выполнения, добавляется еще одно ограничение (не по ctp_auto, а по другому полю). Причем строчка длинная (OR повторяется примерно 500 раз), и опять зависает, причем вешается Windows. Можно как-нибудь эту проблему обойти?


 
sniknik ©   (2004-05-31 11:55) [46]

> причем вешается Windows. Можно как-нибудь эту проблему обойти?
конечно! переходи на линух, будет вешатся он.

индексы то добавил? и освети текушее положение дел, если ты думаеш что мы в курсе то глубоко ошибаешся. особенно интересно что скрывается за глубокомыссленным "Не пашет".


 
Andrey   (2004-05-31 11:57) [47]

Напишу минут через 30. Сейчас убегаю на обед :)


 
Andrey   (2004-05-31 14:15) [48]

В общем, принято радикальное решение снести к черту MySQL и использовать MS SQL. Терпение кончилось, когда из таблицы contract исчезли 75% записей.


 
Vlad ©   (2004-05-31 14:17) [49]


> Andrey   (31.05.04 14:15) [48]


> В общем, принято радикальное решение снести к черту MySQL
> и использовать MS SQL

Без необходимых индексов и там работать не будет.


> Терпение кончилось, когда из таблицы contract исчезли 75%
> записей.

Вот так прям взяли и исчезли ? :-)


 
Andrey   (2004-05-31 15:58) [50]


> Без необходимых индексов и там работать не будет.


В MS SQL работает. Можешь поздравить :)


> Вот так прям взяли и исчезли ? :-)


Да, причем три раза подряд. С базой работаю только я, права у меня только на чтение, т.е. я сам стереть никак не могу. Мистика, блин :)


 
Vlad ©   (2004-05-31 16:02) [51]


> Andrey   (31.05.04 15:58) [50]


> В MS SQL работает. Можешь поздравить :)

Чтож, поздравляю :-)
Если верить твоим словам, вывод можно сделать только один - в MySQL либо нет оптимизатора запроса либо он просто корявый.


 
Andrey   (2004-05-31 16:10) [52]


> Чтож, поздравляю :-)
> Если верить твоим словам, вывод можно сделать только один
> - в MySQL либо нет оптимизатора запроса либо он просто корявый.


У меня вывод более радикальный: херня это полная. Как говорится, бесплатный сыр только в мышеловке.

Но я все равно не понял, почему не выполняется такой простой запрос. Хотя, фиг с ним.


 
Anatoly Podgoretsky ©   (2004-05-31 16:54) [53]

Странно, выходит что сначала выбрали базу, а потом стали разбираться подходит она или нет. Обычно делают наоборот.


 
Курдль ©   (2004-05-31 17:47) [54]


> Открытие той же таблицы через TTable (с установленным индексом)
> происходит почти сразу (через пару секунд).

А Вы уверены, что TTable фетчит все записи? Мне сдается, что она показывает малую часть НД и подгружает по мере скроллинга.


 
Vlad ©   (2004-05-31 17:49) [55]


> Курдль ©   (31.05.04 17:47) [54]

Так и есть, все настройки в BDE алиасе, в т.ч. и курсор (клиентский/серверный), а так же количество записей в одном пакете (ROWSETSIZE)


 
Курдль ©   (2004-05-31 17:52) [56]

А о чем тогда сыр-бор? 30 секунд для MySQL и указанного в [4] запроса с выборкой 6 000 000 записей - это невероятно быстро!


 
Vlad ©   (2004-05-31 17:58) [57]


> Курдль ©   (31.05.04 17:52) [56]

Речь о результирующем наборе данных, там же не 6 млн записей, а к примеру 100-200, это должно быстро срабатывать даже при полном фетче.


 
Izyum ©   (2004-06-01 10:36) [58]

так если все живет через БДЕ, если мне память не врет, Query сначала стягивает все НД на локальный комп, а потом их обрабатывает, а Table действительно фетчит их при необходимости... Отсюда и мнимое преимущество TTable...



Страницы: 1 2 вся ветка

Форум: "Базы";
Текущий архив: 2004.06.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.6 MB
Время: 0.033 c
10-1013431792
comwad
2002-02-11 15:14
2004.06.27
Corba ест память!!!


3-1086259092
Shadow Of Templar
2004-06-03 14:38
2004.06.27
Проблема с внешними файлами в FireBird


14-1086858146
Verg
2004-06-10 13:02
2004.06.27
Странное мышление


14-1086949113
Polevi
2004-06-11 14:18
2004.06.27
реклама


1-1087143779
AbLaZe
2004-06-13 20:22
2004.06.27
Меню





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский