Идеально воспроизводимая проблема выбора оператора по умолчанию
Недавно я преследовал проблему с найденным клиентом db... решением, но его невозможно воссоздать.
По сути, мы делаем
Select * from mytable where ArbitraryColumn = 75
Где MyTable имеет столбец Identity, который называется "MyIndentityColumn" - увеличивается на единицу при каждой вставке. Естественно, и обычно я предполагаю, что возвращаемый порядок будет тем порядком, в котором они вставлены (ошибочное предположение, но навязанное мне через унаследованное приложение - которое было исправлено).
По сути, я хотел бы получить предложения о том, почему при восстановлении на моем локальном компьютере (той же ОС, той же версии SQL-сервера - 200 sp3) такая же сортировка и тот же экземпляр резервной копии, восстановленный на ней, как тестовая БД на клиентском сайте.
Когда я выполняю вышеупомянутый выбор, я получаю их в порядке вставки (то есть столбец идентичности упорядочен по возрастанию). На клиенте это кажется случайным (но каждый раз один и тот же "случайный" порядок)...
Несколько других моментов:
- У меня на тестовом сервере такое же сопоставление, как и у клиента
- Та же самая резервная копия БД восстановлена до теста, только я могу получить доступ
- Та же версия сервера SQL и пакет обновления
- Та же ОС
- Тестовая БД - это новая БД - новый лог и MDF...
У меня проблема "решена" путем добавления явного порядка с помощью предложения, но я хочу устранить причину проблемы, учитывая точный характер моих попыток воссоздать ее, так как она бесполезна и прекрасно поддается восстановлению на клиентском сервере...
Заранее спасибо,
Дейв
3 ответа
Порядок набора записей определяется только самым внешним ORDER BY.
Во избежание сомнений: нет порядка сортировки по умолчанию
Упомянутый вами "воспроизводимый" порядок отражает только то, как SQL Server читает данные в плане выполнения для вашего сервера в то время. Тот же пакет обновления? То же издание? Такое же количество процессоров (включая HT)? Точно такие же параметры SET?
Если план изменится, возможно, изменится и порядок. Это не имело никакого отношения к порядку вставки или порядку индекса или расположению диска.
Этот вопрос принадлежит StackOverflow и на него уже отвечали:
- https://stackoverflow.com/questions/1793147/sql-best-practice-to-deal-with-default-sort-order
- https://stackoverflow.com/questions/1707506/are-the-results-deterministic-if-i-partition-sql-select-query-without-order-by
- так далее
С MSDN, сортировка строк с помощью ORDER BY
ORDER BY гарантирует отсортированный результат только для самой внешней инструкции SELECT запроса. Например, рассмотрим следующее определение представления
Из блога Конора,
Рассматривает ли оптимизатор запросов SQL Server фрагментацию индекса при выборе плана?
Нет, это напрямую не волнует.
Порядок, в котором возвращаются записи, зависит от вашей индексации. В игру вступают три вещи:
- какой индекс используется в запросе и является ли ваша идентификационная колонка основной частью индекса.
- Насколько фрагментирован используемый индекс. Если он сильно фрагментирован, то записи наверняка будут возвращены не по порядку.
- Индекс, который вы используете кластерный индекс для этой таблицы
Единственный способ гарантировать порядок возвращаемых записей - использовать оператор ORDER BY. Если вы зависите от определенного порядка возвращаемого набора записей, то вы должны использовать оператор ORDER BY.
После тщательного расследования мы обнаружили проблему с маршрутом...
У клиента был дополнительный индекс для таблицы, который выбрасывал все синхронизированные, но только на своем сервере. При локальном тестировании, резервном копировании LDF/MDF или восстановлении в свежую базу данных - проблема не обнаружена.
На клиентском компьютере, в исходном файле mdf/mdf, после резервного копирования и восстановления или в новой базе данных, на которую было восстановлено, проблема выставлена на 100% надежно.
В качестве доказательства того, что индекс был причиной, мы могли бы удалить и повторно добавить индекс и увидеть, что нежелательное поведение происходит, а затем не происходит.