08.12.2016, 13:07 | #1 |
Участник
|
Запросы из AX на уровне SQL как Cross Join
Коллеги, добрый день!
2012R3, SQL 2014 Кто сталкивался с проблемой Cross Join Пишется обычный запрос на Ах: X++: select RecId from Header join RecID from line where line.headerRecid == Header.RecId && line.someField == 12345 X++: select RecId from Header CROSS JOIN RecID from line where line.headerRecid == Header.RecId && line.someField == 12345 X++: select RecId from Header Inner join RecID from line ON line.headerRecid == Header.RecId && line.someField == 12345 Есть ли что-то, что позволяло бы однозначно уводить запрос в Inner Join? Какие параметры влияют на то, что запрос строится с помощью Cross Join? Если нужно конкретно, могу вытащить сюда конкретные запросы, таблицы кастомные, но думаю такая же история будет и в системных |
|
08.12.2016, 13:24 | #2 |
Участник
|
а в чем проблема?
|
|
08.12.2016, 13:31 | #3 |
Участник
|
|
|
08.12.2016, 14:00 | #4 |
Участник
|
Cross Join по факту умножает кол-во записей между собой.
+ Where отрабатывает только в после объединения Cross. В случае Inner Join ON сначала ограничивает выборку, затем объединяет только по нужным. В желаемом варианте исключена избыточная перекрестная выборка, а также исключена излишняя выборка из-за переноса условий в блок ON. Нет, точно не используется У меня подозрение в сторону каких-то параметров таблиц. Возможно в Relation свойства надо другие ставить, может ли это влиять или точно нет? |
|
08.12.2016, 14:24 | #5 |
Участник
|
Цитата:
Все зависит от того, как распределены данные (статистика), какие именно созданы индексы и еще кучи других условий Вот вам два разных запроса, с абсолютно одинаковыми планами X++: select top 100 * from INVENTJOURNALTABLE ij inner join INVENTJOURNALTRANS ijt on ij.DATAAREAID = ijt.DATAAREAID and ij.JOURNALID = ijt.JOURNALID where ij.JOURNALTYPE = 0 X++: select top 100 * from INVENTJOURNALTABLE ij cross join INVENTJOURNALTRANS ijt where ij.DATAAREAID = ijt.DATAAREAID and ij.JOURNALID = ijt.JOURNALID and ij.JOURNALTYPE = 0 По поводу хинта forceNestedLoop. Он, в принципе, наоборот заставит использовать inner join, но с обязательным хинтом inner loop join. Т.е. будет принудительно устанавливаться алгоритм объединения
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
08.12.2016, 15:33 | #6 |
Участник
|
За чтож вы так не любите команду которая занимается разработкой движка оптимизатора SQL Server
|
|
09.12.2016, 12:27 | #7 |
Участник
|
If you run the following X++ code and look at the Transact-SQL trace, you will see CROSS JOIN in the Transact-SQL statement. You might think that it misses the join condition and is doing a Cartesian product of the two tables. The join condition is actually in the where clause. A cross join like this is equivalent to an inner join with the join condition.
Источник |
|
09.12.2016, 13:04 | #8 |
Участник
|
Цитата:
Эквивалентны функционально. Но не эквивалентны с точки зрения производительности. А вот дальше в книге приводится причина - outer join. Pokersky09, в вашем запросе outer join есть? |
|
09.12.2016, 13:35 | #9 |
Участник
|
Честно говоря, не понимаю общего "возбуждения"
Не знаю, как в Ax2012, но в младших версиях Axapta никогда не посылала на SQL запросы с объединением по Inner Join. Всегда на SQL отправлялись запросы вида X++: select Header.RecId, line.RecId from Header, line where line.headerRecid == Header.RecId AND line.someField == 12345 Так что, можете считать это фичей Axapta. Ну, вот таким образом она конструирует синтаксис запроса. Ничего с этим не поделаешь В общем случае, на производительность это не влияет, кроме очень особых ситуаций
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
09.12.2016, 22:10 | #10 |
Участник
|
Нет, чисто Inner Join.
Цитата:
По производительности отличие существенное, когда в таблице Line 200KK+ записей, а в Header порядка 120К+(этот случай в бд разбираю). На уровне SQL выполняя запросы на CROSS/INNER скорость существенно отличается, на кросе около 800ms самый хороший результат. Пробовал на sql, тестил только планы запросов, без замеров времени: Inner / Inner loop join, отличались циклом от варианта без loop, Cost запроса CROS/INNER/LOOP_INNER = 44/44/13 Т.е. по стоимости по плану loop_Inner наиболее быстрый. Планы CROS/INNER одинаковые, как и цена. Позже выложу скрины по факту с временем, планами запросов и показателями таблиц P.s. тему поднял не для теоретического рассуждения, а для реального решения проблемы Последний раз редактировалось Pokersky09; 09.12.2016 в 22:12. Причина: отличались циклом от варианта без loop* |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
09.12.2016, 22:21 | #11 |
Участник
|
Цитата:
Цитата:
Получится как AndyD говорит? |
|
13.12.2016, 01:40 | #12 |
Administrator
|
Да эквивалентны они. AndyD выше уже показал, что план выполнения запроса будет совершенно одинаковый.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
Теги |
cross join, inner join, sql 2014 |
|
|