Порядок строк по строкам в запросе SELECT - SQL Server 2008 vs SQL 2012

Наша команда недавно обновила наши базы данных с SQL Server 2008 до SQL Server 2012. Одно замечание, которое мы заметили, было в стандартном порядке строк, возвращаемых оператором SELECT, то есть когда явное предложение ORDER BY не указано.

В соответствии с MSDN SQL Server 2012 не упорядочивает порядок возвращаемых строк, если не указано условие ORDER BY.

У нас есть 2500+ хранимых процедур в 5 базах данных, которые имеют инструкции SELECT без предложения ORDER BY, и это будет значительное усилие, чтобы добавить предложение ORDER BY вручную, чтобы соответствовать поведению в SQL Server 2008. Есть ли настройка или быстрее способ сделать это?

Другим вариантом, который не был изучен, является переход на SQL Server 2008. Насколько это сложно?

Ответ 1

Вам нужно вернуться и добавить в свой код ORDER BY, потому что без них заказ никогда не будет гарантирован. В прошлом вам "повезло", что у вас всегда был тот же порядок, но это было не потому, что SQL Server 2008 гарантировал его в любом случае. Скорее всего, это связано с вашими индексами или тем, как данные хранятся на диске.

Если вы переместились на новый хост при обновлении разницы в конфигурации оборудования, это могло бы изменить способ выполнения ваших запросов. Не говоря уже о том, что новый сервер пересчитал статистику по таблицам, а оптимизатор запросов SQL Server 2012, вероятно, немного изменит ситуацию, чем в SQL Server 2008.

Ошибочно, что вы можете положиться на порядок набора результатов в SQL, явно не указав порядок, в котором вы хотите. Результаты SQL НИКОГДА имеют порядок, на который вы можете положиться, без использования ORDER BY. SQL построен вокруг теории множеств. Результаты запроса в основном являются наборами (или несколькими наборами).

Ицик Бен-Ган дает хорошее описание теории множеств по отношению к SQL в своей книге Основы SQL-SQL для Microsoft SQL Server 2012

Теория множеств, которая возникла у математика Георгия Кантора, одна из математических ветвей, на которых реляционная модель исходя из. Определение кантора определяется следующим образом:

Под "множеством" понимается любое множество M в целое определенное, определенное объекты m (которые называются "элементами" M) нашего восприятия или нашей мысли. - Джозеф У. Даубен и Георг Кантор (Принстон) University Press, 1990)

После подробного объяснения терминов в определении Ицик затем продолжает:

То, что изъятие Кантора для определения уходит, вероятно, так же важно как то, что он включает. Обратите внимание, что в определении не упоминается никаких порядок среди множества элементов. Порядок, в котором установлены элементы перечисленные не являются важными. Формальная запись для перечисления элементов набора использует фигурные скобки: {a, b, c}. Поскольку заказ не имеет значения, вы можете выражают то же множество, что и {b, a, c} или {b, c, a}. Прыжки вперед к набор атрибутов (называемых столбцами в SQL), которые составляют заголовок отношение (называемое таблицей в SQL), предполагается, что элемент идентифицируется по имени - не порядковая позиция. Аналогично рассмотрим множество кортежей (называемых строками по SQL), которые составляют тело отношения; элемент идентифицируется по его ключевым значениям, а не по положению. Многие программисты с трудом адаптируются к идее, что с уважением для запросов к таблицам нет порядка среди строк. Другими словами, запрос к таблице может возвращать строки в любом порядке, если только вы не явно запросить сортировку данных определенным образом, возможно для целей презентации.

Но независимо от академического определения набора даже реализация на SQL-сервере никогда не гарантировала какого-либо заказа в результатах. Это сообщение сообщения MSDN от 2005 года членом команды оптимизатора запросов утверждает, что вы не должны полагаться на заказ из промежуточных операций вообще.

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

Это сообщение в блоге Конор Каннингем (Architect, SQL Server Core Engine) "No Seatbelt - ожидающий заказ без ORDER BY" относится к SQL Server 2008. У него есть таблица с 20k строками в ней с единственным индексом, который, как представляется, всегда возвращает строки в том же порядке. Добавление ORDER BY к запросу даже не изменяет план выполнения, поэтому не похоже на добавление одного из них, что делает запрос более дорогим, если оптимизатор понимает, что он ему не нужен. Но как только он добавит еще 20k строк в таблицу, внезапно изменится план запроса, и теперь он использует parallelism и , результаты больше не упорядочены!

Трудная часть здесь заключается в том, что нет разумного способа для любого внешнего чтобы узнать, когда изменится план. Пространство всех планов огромно и болит головой, чтобы обдумать. Оптимизатор SQL Server изменится планы, даже для простых запросов, если достаточно изменить параметры. Вам может повезти, и у вас нет изменений плана, или вы можете просто не подумайте об этой проблеме и добавьте ORDER BY.

Если вам нужно больше убеждать, просто прочитайте эти сообщения: