Почему порядок предложений соединения влияет на план запроса в SQL Server?

Отмена, что, я был неправ. (См. комментарии.) можно предотвратить использование путем обеспечения, что JSON следует за спецификацией: Всегда удостоверяйтесь, что Вы возвращаете литерал объектов как объект верхнего уровня. (Я не могу гарантировать, что не будет дальнейшего использования. Вообразите доступ обеспечения браузера к неудавшемуся коду в его window.onerror событиях!)

Вы не можете полагаться на правила перекрестных сценариев сайта сохранить ответы Ajax частными. Например, при возврате маркера CSRF как JSON злонамеренный сайт мог переопределять Строку или Конструктора Array и запрашивать ресурс.

bigmattyh корректен: необходимо встроить маркер где-нибудь в разметку. С другой стороны, Вы могли отклонить любые СООБЩЕНИЯ, которые делают , имеют ссылающийся домен, который не делает соответствие. Тот путь, только люди с фанатичными программными брандмауэрами будут уязвимы для CSRF.

11
задан Community 23 May 2017 в 12:13
поделиться

7 ответов

Я не согласен со всеми предыдущими ответами, и причина проста: если вы измените порядок своего левого соединения, ваши запросы будут логически разными и, как таковые, они производят разные наборы результатов. Убедитесь сами:

SELECT 1 AS a INTO #t1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4;

SELECT 1 AS b INTO #t2
UNION ALL SELECT 2;

SELECT 1 AS c INTO #t3
UNION ALL SELECT 3;

SELECT a, b, c 
FROM #t1 LEFT JOIN #t2 ON #t1.a=#t2.b
  LEFT JOIN #t3 ON #t2.b=#t3.c
ORDER BY a;

SELECT a, b, c 
FROM #t1 LEFT JOIN #t3 ON #t1.a=#t3.c
  LEFT JOIN #t2 ON #t3.c=#t2.b
ORDER BY a;

a           b           c
----------- ----------- -----------
1           1           1
2           2           NULL
3           NULL        NULL
4           NULL        NULL

(4 row(s) affected)

a           b           c
----------- ----------- -----------
1           1           1
2           NULL        NULL
3           NULL        3
4           NULL        NULL
6
ответ дан 3 December 2019 в 07:14
поделиться

Порядок соединения действительно влияет на результирующий запрос. Это задокументировано в BOL в документации для FROM :

Это набор результатов, который является продуктом двух или более таблиц. Для нескольких объединений используйте круглые скобки, чтобы изменить естественный порядок объединений .

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

Это известно как хиастическое поведение. Вы также можете использовать подсказку запроса OPTION (FORCE ORDER) , чтобы принудительно установить определенный порядок соединения, но это может привести к так называемым «кустарниковым планам», которые могут не быть самыми оптимальными для выполняемого запроса.

3
ответ дан 3 December 2019 в 07:14
поделиться

Общая стратегия оптимизации запросов, содержащих JOIN, состоит в том, чтобы взглянуть на вашу модель данных и данные и попытаться определить, какие JOIN уменьшат количество записей, которые должны быть рассмотрены наиболее быстро. Чем меньше записей необходимо учитывать, тем быстрее будет выполняться запрос. Сервер обычно также создает лучший план запроса.

Наряду с указанной выше оптимизацией убедитесь, что все поля, используемые в JOINs, проиндексированы

2
ответ дан 3 December 2019 в 07:14
поделиться

Очевидно, оптимизатор SQL Server 2005 намного лучше, чем оптимизатор SQL Server 2000.

Однако в вашем вопросе много правды. Внешние соединения приведут к тому, что выполнение будет сильно различаться в зависимости от порядка (внутренние соединения, как правило, оптимизируются для наиболее эффективного маршрута, но, опять же, порядок имеет значение). Если вы думаете об этом, когда вы создаете левые соединения, вам нужно выяснить, что, черт возьми, находится слева. Таким образом, каждое соединение должно быть вычислено до того, как может быть выполнено любое другое соединение. Он становится последовательным, а не параллельным. Теперь, очевидно, есть вещи, которые вы можете сделать для борьбы с этим (например, индексы, представления и т. Д.). Но суть в том, что таблица должна знать, что находится слева, прежде чем она сможет выполнить левое внешнее соединение. И если вы просто продолжаете добавлять объединения, вы получаете все больше и больше абстракции от того, что,

2
ответ дан 3 December 2019 в 07:14
поделиться

это зависит от того, какое из полей соединения проиндексировано - если он должен сканировать таблицу по первому полю, но использовать индекс во втором, это медленно. Если ваше первое поле соединения является индексом, это будет быстрее. Я предполагаю, что 2005 оптимизирует его лучше, определяя индексируемые поля и выполняя их первыми

1
ответ дан 3 December 2019 в 07:14
поделиться

Несколько лет назад на DevConnections в ходе сеанса по производительности SQL Server было заявлено, что (а) порядок внешних соединений ДЕЙСТВИТЕЛЬНО имеет значение, и (б) когда в запросе много соединений, он не будет посмотрите на них все, прежде чем определиться с планом. Если вы знаете, что у вас есть объединения, которые помогут ускорить запрос, они должны быть в начале списка FROM (если вы можете).

1
ответ дан 3 December 2019 в 07:14
поделиться

Возможно, вы все равно ошиблись. Алекс прав. Эрик тоже может быть прав, но запрос неверен.

Давайте возьмем это подмножество:

WTSA_SessionRange sr
left outer join
WTSA_SessionSubrange ssr on ssr.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join
WTSA_SessionSubrangeRoom ssrr on ssrr.WTSASessionSubrangeID = ssr.WTSASessionSubrangeID

Вы присоединяетесь к WTSA_SessionSubrangeRoom на WTSA_SessionSubrange. У вас может не быть строк из WTSA_SessionSubrange.

Соединение должно быть таким:

WTSA_SessionRange sr
left outer join
(SELECT WTSASessionRangeID, columns I need
FROM
    WTSA_SessionSubrange ssr
    left outer join
    WTSA_SessionSubrangeRoom ssrr on ssrr.WTSASessionSubrangeID = ssr.WTSASessionSubrangeID
) foo on foo.WTSASessionRangeID = sr.WTSASessionRangeID

Вот почему порядок соединения влияет на результаты, потому что это другой запрос , декларативно говоря.

Вы бы сделали это. также необходимо изменить соединение MO_Stream и WTSA_SessionRangeStream .

2
ответ дан 3 December 2019 в 07:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: