04.12.2006, 12:18 | #1 |
Участник
|
Разница между запросами
Подскажите, кто знает, есть ли разница между запросами:
1) select A join B where A.Field1 == param1 && B.Field1 == param2 && A.Field2 == B.Field2 2) select A where A.Field1 == param1 join B where B.Field1 == param 2 && B.Field2 == A.Field2 Relatoins между таблицами нету. |
|
04.12.2006, 12:23 | #2 |
Участник
|
логической разницы нет - вы получите одинаковые результаты.
разница только в скорости - вы получите одинаковые результаты с разной скоростью. скорость зависит от многих вещей: 1. прежде всего от размера таблиц 2. от индексов 3. от параметров оптимизатора 4. от параметров самой аксапты (как она помогает оптимизатору) |
|
04.12.2006, 14:18 | #3 |
Участник
|
1) Таблица А сдержит порядка 20'000'000 записей, В - 15'000
2) Для таблицы В при выполнении запроса индекс используется. Здесь всё нормально. Для таблицы А происходит full scan. Как я понимаю, существующий индекс при этом не используется в первом случае как раз из-за структуры запроса? (оба эти запроса на скорость выполнения пока протестировать не имею возможности) 3), 4) можно немного поподробнее? Какие параметры можно смотреть? |
|
04.12.2006, 14:37 | #4 |
Moderator
|
В общем - одно время московский MBS грешил привычкой указывать условия джойна в условии where в конце запроса. Ну то есть - что нибудь типа:
select a join b join c join d where a.field1==b.field1 and c.field2=b.field2 and d.field3==a.field2 Так вот на одном из проектов (где-то в недрах книг покупок/продаж) обнаружилось что такой код, хоть и отрабатывает, но выполняется неадекватно много времени. Как показало вскрытие, если MS SQL обрабатывает join нескольких таблиц без условия where для каждого join, то он СНАЧАЛА всегда строит картезианское произведение этих таблиц и только потом накладывает на него условия из последнего where (в котором с его точки зрения должны стоять не условия джойнов, а условия фильтрации результата). После того как я это дело вылечил - написал в MBS и они у себя в этом конкретном месте подправили в новых сервис-паках. Возможно - в каких-то других местах кода подобные нехорошие джойны остались. Не уверен. Кроме того - это кажется на MS SQL 2000 SP3 было. Может с тех пор сам SQL Server научился более грамотно подобные запросы обрабатывать. |
|
|
За это сообщение автора поблагодарили: belugin (10), Russland (1). |
04.12.2006, 14:49 | #5 |
Участник
|
2 fed,
У нас используется Oracle. Как он реагирует на подобные вещи - не знаю, но есть подозрение что как раз возникает подобная ситуация. На днях думаю появится возможность это проверить. |
|
04.12.2006, 15:32 | #6 |
Участник
|
Если такое соотношение будет и в будущем и будет примерно постоянным, то лучше
select B where B.Field1 == param 2 join A where A.Field1 == param1 B.Field2 == A.Field2 Цитата:
Сообщение от Rect
2) Для таблицы В при выполнении запроса индекс используется. Здесь всё нормально. Для таблицы А происходит full scan. Как я понимаю, существующий индекс при этом не используется в первом случае как раз из-за структуры запроса? (оба эти запроса на скорость выполнения пока протестировать не имею возможности)
Но надо смотреть. Я не понимаю утверждения "не имею возможности протестировать скорость". Вы задаете теоретические вопросы? Создайте пару таблиц, заполните их и попробуйте. Если такие таблицы есть, то почему нет возможности протестировать? Для начала в конфигурационной утилите все что связано с literal'ами, order by clause from where прочитайте про хинты nestedloop и т.п. http://axapta.mazzy.ru/lib/indexhints/ Потом читайте про работу оптимизатора в BOL. про статистику и т.п. |
|
04.12.2006, 18:02 | #7 |
Участник
|
О, знакомый симптом: классы FactureCalcSettlement_RU, FactureCalcBalances_RU метод calcFactureAmounts. Простое изменение порядка условий ускорило выполнение почти в 100 раз!
|
|
|
За это сообщение автора поблагодарили: Denicce (1). |
05.12.2006, 08:40 | #8 |
Злыдни
|
Есть по этому поводу хорошая книга Д.Тоу "Настройка SQL. Для професионалов", в которой рассмотрен порядок соединения исходя из веса возвращаемых данных из связанных таблиц и условий фильтрации. Наличие правильной статистики и тюнинг запроса иногда кардинально улучшают скорость выборки.
__________________
люди...считают, что если техника не ломается, то ее не нужно ремонтировать. Инженеры считают, что если она не ломается, то нуждается в совершенствовании. |
|
05.12.2006, 10:04 | #9 |
----------------
|
Есть мнение, что разницы между запросами из 1го поста нет, так как Аксапта сгенерит из них совершенно одинаковые SQL-предложения.
|
|
05.12.2006, 10:30 | #10 |
Участник
|
Согласен с Wamr - запросы получатся в принципе похожие.
Различие будет в порядке следования полей в предложении where и в расстановке скобок. И более того - перестановка таблиц в селекте тоже не будет иметь эффекта. Думаю, что причина неиспользования индекса по таблице A в том, что запрос по таблице B возвращает множество записей. Причем, скорее всего, включены плейсхолдеры, в результате чего оптимизатор не может предсказать статистику для запроса по таблице B и по-этому идет по пессимистичному плану. А дальше - уже рашает, что сканирование по таблице A будет дешевле. Как варианты: 1. Попробовать включить литералы (forceliterals) в запросе. Не уверен действенности этого совета. Все зависит от правильности статистики по таблицам и распределении значений. 2. Попробовать явно указывать индексные хинты для таблицы A. Опять-таки - все зависит от распределения значений по таблицам. В принципе - это в большой степени экспериментальный путь 3. Самый простой путь - разбить запрос на два. Внешний цикл - по таблице B. Внутри цикла - запрос по таблице A. При этом для внутреннего запроса явно указать forceplaceholders.
__________________
Axapta v.3.0 sp5 kr2 |
|
05.12.2006, 10:39 | #11 |
Участник
|
При соединении 2-х таблиц возможно Аксапта и перестроит запрос сама. А вот при большем количестве таблиц - точно нет. Причем, даже оптимизатор MS SQL (по крайней мере MS SQL 2000) не справится. Пример с методом calcFactureAmounts вполне реальный.
|
|
05.12.2006, 10:43 | #12 |
Участник
|
2 fed
Думаю, что ваше замечание относится к запросу такого вида X++: select a exists join b where a.parm1 == parm1 && a.filed1 == b.field1 X++: select * from a where exists(select 'x' from b where a.parm1 = parm1 and a.field1 = b.field1) Т.е. при таком запросе условие a.parm1 == parm1 накладывается не на таблицу A, а на связь таблицы A и таблицы B. Будут выбраны все записи для таблицы A и для каждой из них будет вызван внутренний селект. С точки зрения логики запросы будет идентичны - в обоих случаях получаем идентичный набор записей Кстати, замечание Raven Melancholic - как раз для такого типа запросов. Это же относится и к notexists join запросам. Для простого join'а будет генерировать такой запрос X++: select * from a, b where (a.dataareaid = 'EXT') and ((b.adataareaid = 'EXT') and ((a.parm1=parm1) and (a.field1=b.field1)))
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: Logger (2). |
05.12.2006, 12:14 | #13 |
Участник
|
если исходита из теории БД то второе условие более правильное т.к. выборка при этом меньше, ведь не все записи из таб А обединяются с Б а только нужные, из-за чего происходит этономия времени и ресурсов
|
|
05.12.2006, 12:44 | #14 |
Moderator
|
to andyD.
Посмотрел. Действительно в последних sp генерируется правильный джойн. А вот года два с лишним назад (тогда кажется sp1 был) для такого запроса генерировалось что-то типа select * from a inner join b on a.dataAreaid=b.dataareaid inner join c.dataareaid=a.dataAreaId where a.field1=b.field2 и т.п. И от таких запросов оптимизатор регулярно уводило в картезианское произведение таблиц. Или там даже в явном виде генерировалось ядром аксапты слово cross join... Не помню уже если честно Но в общем - переделка таких запросов реально на порядок ускоряло работу. |
|
Теги |
производительность, запрос (query), axapta |
|
|