Заметки Дмитрия Пилюгина о Microsoft SQL Server 

Twitter RSS
formats

Медленно в приложении, быстро в SSMS (часть 1)

Давненько я хотел написать что-нибудь на эту тему. Однако, пока я собирался с мыслями и силами, наткнулся на уже написанную статью Slow in the Application, Fast in SSMS? Understanding Performance Mysteries Erland-а Sommarskog, которая исчерпывающе отвечает на поставленный вопрос. Так что мне осталось только представить перевод этой статьи, который я для удобства разделил на три части.

Введение

Когда я просматриваю различные форумы по SQL Server, я часто вижу вопросы от глубоко озадаченных пользователей. Они нашли медленный запрос или процедуру в своем приложении. Переместили этот пакет из своего приложения в SQL Server Management Studio (SSMS), чтобы проанализировать и обнаружили, что ответ от сервера приходит мгновенно. С этого момента они начинают думать что SQL Server это нечто магическое. Похожая загадка происходит и в случае если разработчик извлекает запрос из своей хранимой процедуры, чтобы выполнить его отдельно, но обнаруживает что он выполняется гораздо быстрее — или гораздо медленнее — чем внутри хранимой процедуры.
Нет, SQL Server это не магия. Но если у вас нет хорошего понимания того как SQL Server компилирует запросы и поддерживает кэш планов выполнения, так может показаться. Кроме того есть некоторые неудачные комбинации различных настроек по умолчанию в некоторых средах. В этой статье я постараюсь разъяснить, почему вы получаете такое, казалось бы, не согласующееся поведение. Я объясню, как sql server компилирует хранимую процедуру, что такое прослушивание параметров (parameter sniffing) и почему оно является важной частью уравнения в большинстве сбивающих с толку ситуаций. Я объясню, как sql server использует кэш, и почему в кэше может быть несколько записей для одной процедуры. Стоит только копнуть глубже, и вы поймете, как получается так, что запрос в SSMS выполняется гораздо быстрее.
Читать дальше…

 
formats

Выбор полей для кластерного индекса

Существуют разные точки зрения на тему, какое поле лучше всего подходит в качестве кластерного индекса для таблицы. В частности такое «кластерный индекс должен удовлетворять запросам для выбора большого числа строк, желательно что бы это не было поле identity, т.к. при такой организации могут возникать hotspot при вставке, а выбор по диапазону identity явление очень редкое».
Так же есть мнения, что такой подход уже давно не актуален в новых версиях, а выбор в качестве кластерного индекса например поля guid — ведет к фрагментации. Для себя я выработал некоторое мнение по этому вопросу. А недавно наткнулся на интересную статью по выбору поля для кластерного индекса в блоге Kimberly L. Tripp, которая еще больше подтвердила некоторые мои мысли относительно этого.
Хотя статья не новая, но мне кажется она может быть полезна людям которые задавали или задают себе этот вопрос. По этому, привожу свою версию перевода статьи.

Читать дальше…

 
formats

Некоторые случаи необрабатываемые блоком try/catch

Возможно, не все знают, что в t-sql конструкция try catch обрабатывает не все ошибки.
Это поведение хорошо документировано, но может стать сюрпризом для людей привыкших работать с классическим try/catch в объектно-ориентированных языках.
Подробно это описано в документации TRY…CATCH (Transact-SQL), Использование конструкции TRY…CATCH в языке Transact-SQL — я же просто приведу некоторые примеры, на которые наталкивался сам.

Читать дальше…

 
Теги:, ,
formats

Можно ли отсортировать результаты во вью?

Ответ: можно, но это не правильно, т.к. недокументировано.
Согласно документации предложение order by запрещено во вью (если не указан оператор top, но и тогда порядок не гарантируется) и если вам нужно получить отсортированный результат из вью — то предложение order by необходимо указывать в запросе к этому вью.
Тем не менее, отсортированные данные получить все-таки можно, т.к. «как правило» (чисто эмпирически) top совместно с order by приводит к сортировке в плане (однако т.к. это не документировано само собой нет гарантии, что так будет всегда).
Рассмотрим некоторые из способов создания такой сортировки.

Читать дальше…

 
formats

Как отключение FK на момент загрузки, может повлиять на план запроса после загрузки

Если в таблице создано ограничение внешнего ключа (Foreign Key Constraint), то при добвлении данных в эту таблицу будет проверяться наличие/отсутствие соответствующих записей в «родительской» таблице.
Иногда, если загрузка данных идет из, условно говоря, доверенного источника (имеется ввиду нам известно, что все данные из источника отвечают требованиям ссылочной целостности), для ускорения загрузки ограничения внешних ключей отключают, а после загрузки — включают обратно.
Смоделируем такую ситуацию и посмотрим, что будет.

Читать дальше…

 
formats

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

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

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

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

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

Читать дальше…

 
formats

Вариант использования процедур sp_trace_XXX для долгосрочной трассировки

monitoring with sp_traceНеобходимость трассировки возникла после жалоб пользователей одного из офисов нашей компании на «внезапно появляющиеся» и столь же «внезапно исчезающие тормоза». Были исследованы планы предположительно «тормозящих» запросов, блокировки, счетчики сервера, канал связи, но явных проблем нигде не обнаружилось. По этому возникла резонная мысль посмотреть, а что происходит на сервере в этот момент, и главное когда именно (точное время) этот момент наступает и когда заканчивается. Для этих целей как раз и используется трассировка.

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

Читать дальше…

 
formats

Получить в триггере текст запроса

Несколько раз встречал подобные вопросы в форумах. Задача, формулируется примерно так. Получить в триггере текст команды, которая привела к тому, что этот триггер сработал.

Это может быть полезно если мы, например, хотим увидеть/залогировать конкретный запрос, который привел к изменению данных. Сразу скажу, что штатный механизм для обеспечения этого на сегодняшний день, в версиях 2000, 2005, 2008 — не предусмотрен. Но тем не менее, что-то похожее можно реализовать с некоторыми ограничениями.

Читать дальше…

 
Теги:,