Как Изменить Один Символ В Коде И Спасти Ситуацию

Понедельник, 9 утра, сообщение в рабочем чате: «Все сломалось, почините».

Согласитесь, неприятная ситуация, особенно когда у вас первый месяц работы, и что-то сломалось в функционале, с которым вы раньше никогда не контактировали, и месяцами его никто не трогал.



Как Изменить Один Символ В Коде И Спасти Ситуацию

Моя реакция в тот момент



Итак, что случилось?

Сразу после просмотра логов все становится понятно (нет): Ошибка таймаута от MS SQL сервера в модуле, который вызывается из клиентского приложения и обрабатывает документы за определенный период, передает их в систему планирования и рассчитывает различные временные и денежные показатели.

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

Поскольку тупо увеличивать максимально возможное время выполнения процедур в настройках сервера — подход для слабаков, пришлось покопаться.

После нескольких тестов и анализов планов выполнения была найдена проблема — директория, полученная в формате xml, записывается в табличную переменную.

После очередного обновления статистики для процедуры был собран новый план выполнения, который максимально неэффективно соединяет эту переменную с основной выборкой.

Моментальное решение — переключиться на temp table, заменив символ @ на # в имени создаваемой таблицы (опускаем тот факт, что в коде они создаются по-разному, один через Decreate, другой через Create, чтобы не испортить название).

Тестируем, получаем время выполнения 1-2 секунды, довольны, заходим в продакшн, все довольны (особенно я).



Как Изменить Один Символ В Коде И Спасти Ситуацию

Я в глазах пользователей после этой истории (по моему скромному мнению)



Какая разница?

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

Например, на сайте Microsoft вы можете найти это:

Для табличных переменных не допускается использование DDL. Поэтому, если у вас большой набор строк, который необходимо часто запрашивать, вы можете использовать #table, когда это возможно.

Но помимо отсутствия DDL, разница еще серьезнее:
#СТОЛ @СТОЛ
Память Хранится в базе данных tempdb. Хранится в базе данных tempdb, но имеет функцию передачи в виде переменной.

Возможность изменения структуры после создания.

Да Нет
Возможность создавать индексы и ограничения.

Да Только первичный ключ на момент создания
Доступ Внутри сессии Внутри пакета транзакций одной сессии
Продолжительность жизни Пока сессия активна На данный момент действителен один пакет транзакций
Использование в функциях Нет Да
Простота использования Можно создать и заполнить с помощью команды select to. Не нужно проверять наличие и удалять при перезапуске кусок кода во время разработки
Параллелизм Да Нет
Имеет статистику Да Нет
В общем, это почти вся общая информация, которую легко найти погуглив «ms sql temp table vs tablevariable», но она не помогает понять причину моей конкретной ситуации, поскольку мне не пришлось создавать индексы или использовать другие приемы временных таблиц, достаточно было просто поменять 1 символ и все.





Под капотом

Когда-то вопрос о разнице между этими двумя механизмами привел меня к довольно старому посту.

Один из отрывков гласил:

Многие планы выполнения, включающие табличные переменные, будут отображать одну строку, рассчитанную как результат их выполнения.

Проверка свойств табличной переменной показывает, что SQL Server считает, что табличная переменная имеет нуль ряды Однако результаты, показанные в предыдущем разделе, действительно показывают точную rows count in sys.partitions .

Проблема в том, что в большинстве случаев операторы, ссылающиеся на табличные переменные, компилируются, когда таблица пуста.

И действительно, в плане выполнения процедуры с временной переменной было сказано — скорее всего в вашей таблице 1 запись, поэтому строим запрос так, а не иначе.

План выполнения был сгенерирован так, как если бы мы объединяли таблицу только с одной строкой, поэтому нам не нужно слишком беспокоиться об оптимизации.

Этот пункт нигде конкретно не описан и относится к категории проблем «ну вот так сделано», но это никоим образом не указывает на проблемы с продуктом.

Любой ИТ-молоток имеет свои условности и особенности, с которыми вы можете столкнуться в одной из тысячи задач.





Вместо общей суммы

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

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

Спасибо за прочтение.

Теги: #программирование #оптимизация #sql #отладка #память #Microsoft SQL Server #sql-сервер #таблицы данных #ошибка #ошибка

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2006-05-12 19:16:20
Баллов опыта: 603
Всего постов на сайте: 4
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.