Ms sql история запросов: Как просмотреть историю запросов mssql. – adminbd

Журнал запросов в расширении mssql — SQL Server





Twitter




LinkedIn




Facebook




Адрес электронной почты










  • Статья

  • Чтение занимает 2 мин

Статья описывает функции журнала запросов в расширении mssql для VS Code. Журнал запросов представлен как один из разделов представления SQL Server, которое доступно по умолчанию в боковой панели при установке расширения mssql для VS Code.

Просмотр журнала запросов

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

Каждая строка состоит из трех частей.

  • Значок состояния: значок «✔️» показывает успешное выполнение запроса, а «❌» — ошибку.
  • Текст запроса: текст выполненного запроса.
  • Сведения о подключении: сервер и база данных, к которым выполнялся запрос.

Действия со строками журнала запросов

Если щелкнуть строку журнала правой кнопкой мыши, отобразится меню, где доступны следующие действия:

  • Открыть запрос
  • Выполнить запрос
  • Удалить

Открытие запроса

Пункт Открыть запрос открывает новое окно редактора с текстом выполненного запроса и используемым в нем подключением.

Выполнение запроса

Пункт Выполнить запрос делает то же, что Открыть запрос, но при этом сразу же запускает инструкцию.

Удаление

Пункт Удалить удаляет выбранную строку журнала без возможности восстановления.

Управление журналом запросов

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

Хранение данных

Все данные сейчас хранятся в памяти и удаляются при выходе из приложения. Журнал запросов сеанса не будет доступен в новом окне VS Code.

Очистка всего журнала

Действие очистки журнала целиком также доступно в палитре команд (MS SQL: Очистить весь журнал) и как управляющая кнопка в представлении. Это действие удаляет все строки журнала без возможности восстановления.

Запуск и приостановка ведения журнала

Возможность запускать и приостанавливать ведение журнала запросов доступна в палитре команд (MS SQL: Включить или отключить ведение журнала запросов) и как управляющая кнопка в панели. Когда запись приостановлена, никакие данные о выполнении запросов в журнале не сохраняются.

Дальнейшие действия

  • Использование расширения mssql для запросов к экземпляру SQL
  • Дополнительные сведения о Visual Studio Code
  • Участие в разработке расширения mssql






Поиск медленных запросов в SQL Server

02 Aпреля 2019
Базы данных

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

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

declare @dayportion float;
declare @substringlength int;
set @dayportion=-1.0;
set @substringlength=200;

SELECT TOP 15 
    sum(total_logical_reads) 'Total Logical Reads', 
    sum(total_logical_writes) 'Total Logical Writes',
    sum(total_worker_time) 'Total CPU',
    sum(execution_count) 'Count',
    sum(total_logical_reads) * 100 / (select sum(total_logical_reads) from sys. dm_exec_query_stats where last_execution_time > dateadd(day, @dayportion, getdate())) 'Pct of Reads',
    sum(total_logical_writes) * 100 / (select sum(total_logical_writes) from sys.dm_exec_query_stats where last_execution_time > dateadd(day, @dayportion, getdate())) 'Pct of Writes',
    sum(total_worker_time) * 100 / (select sum(total_worker_time) from sys.dm_exec_query_stats where last_execution_time > dateadd(day, @dayportion, getdate())) 'Pct of CPU',
    sum(total_logical_reads) / sum(execution_count) 'Avg Reads',
    sum(total_logical_writes) / sum(execution_count) 'Avg Writes',
    sum(total_worker_time) / sum(execution_count) 'Avg CPU',
    statement_text
FROM (
        select 
        total_logical_reads, 
        total_logical_writes,
        total_worker_time,
        execution_count,
        substring(SUBSTRING(st.text, (qs.statement_start_offset/2)+1, 
            ((CASE qs.statement_end_offset
              WHEN -1 THEN DATALENGTH(st. text)
             ELSE qs.statement_end_offset
             END - qs.statement_start_offset)/2) + 1), 0, @substringlength) as statement_text
        FROM sys.dm_exec_query_stats qs 
        CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
        WHERE last_execution_time > dateadd(day, @dayportion, getdate())
) x
group by statement_text
ORDER BY 'Pct of CPU' DESC

Этот запрос мне дали коллега в Клике, когда я только начинал там работать. Впоследствии я его немного доработал и улучшил и теперь делюсь с вами. Дело в том, что на рабочих серверах нельзя устанавливать какие-то утилиты или инструменты, которые бы позволили смотреть визуально подобные вещи, и в те времена не так много доступного было.

У SQL Server Management Studio есть встроенная возможность, но очень это визуальное окно, которое подтормаживает. В те моменты, когда база данных тормозит под нагрузкой у меня не удавалось открыть это окно, а выполнить подобный запрос очень легко.

В самом начале есть параметр dayportion – это количество дней, за которые мы хотим получить информацию. Я обычно смотрю за последний день, поэтому параметр равен -1.

Результат отсортирован по колонке Pct of CPU. Это отношение затрат на выполнение запроса к количеству выполнений. Чем медленнее запросы и чаще выполняются, тем выше они будут в результате.

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

Я погонял несколько запросов и у меня получилась вот такая картина:

Самый ужасный запрос – это выборка абсолютно всех людей из таблицы Member. Ну это логично и тут единственный способ оптимизировать – стараться не выполнять такие запросы. Если посмотреть на колонку Count, то видно, что запрос выполнялся только однажды. Это нормально и можно проигнорировать.

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

Второй запрос выполнялся уже два раза:

select * from Member where FacebookProfileID = 7000011

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

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

А теперь я покажу, как то же самое увидеть визуально, с помощью красивых возможностей SQL Server Management Studio. В Object Explorer кликаем правой кнопкой по самому верхнему элементу дерева (там вы должны видеть имя базы данных) и в контекстном меню выбираем Activity Monitor:

Внизу окна должны есть несколько закладок и наиболее интересными являются – Active Expensive Queries и Recent Expensive Queries:

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

Я несколько раз уже показывал, как пользоваться статистикой времени и io:

set statistics time on
set statistics io on

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

Но эти две команды не единственные помощники во время поиска проблемных проблем в запросах.

Я уже показывал, как посмотреть предполагаемый и реальные планы выполнения с помощью SQL Server Management Studio, но то же самое можно увидеть и специальными командами в виде результата запроса.

set showplan_text on

Теперь попробуем выполнить простой запрос типа:

select * from Member where MemberID = 7000001

Вместо реального результата мы должны увидеть план выполнения в виде текста, как показано на следующем рисунке:

Отключаем эту функцию, прежде чем перейти к следующей:

set showplan_text off

А следующей опцией будет showplan_all:

set showplan_all on

Теперь в результате мы увидим не просто план выполнения в виде текста, но и подробные вещи, такие как физическая операция, логическая операция, сколько ожидается обработать строк и сколько использовать CPU. Это все то, что мы видели визуально в плане выполнения раньше, но в этот раз мы это видим в виде результата запроса, колонок и строк. Для очень больших запросов это может быть даже нагляднее, чем визуальная диаграмма.

Отключаем отображение полной информации о плане:

set showplan_all off

Следующая версия того, что мы уже видели – это showplan_xml:

set showplan_xml on

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

А вот если кликнуть на плане, то он откроется в виде визуального представления. SQL Server Management Studio умеет рендерить подобные планы в визуальное представление, которое мы видели раньше. Так что XML будет удобен в тех случаях, когда его нужно отправить кому-то на анализ.

Чтобы проще было сохранять XML кликните на него, чтобы открыть визуальное представление. Теперь здесь кликаем правой кнопкой и появляется опция – Save Execution Plan As. ..

Теперь мы можем познакомиться с реальным планов выполнения. До сих пор это была информация о предполагаемом плане выполнения. Я показывал вам, что SQL Server Management Studio позволяет визуально посмотреть предполагаемый и реальный план. То же самое и в виде кода.

Итак, реальный план включаем командой:

set statistics profile on

Теперь если выполнить запрос, то мы увидим в панели результата не только реальную найденную строку, но и план выполнения:

То есть перед нами реальный план выполнения, что реально использовалось при выполнении запроса, сколько раз происходили обращения к таблицам и так далее.

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

set statistics profile off

А следующая команда – это отображение реального плана выполнения в XML формате:

set statistics xml on

В результате мы увидим не только результирующую строку, но XML, в котором будет реальный план.

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


Внимание!!! Если ты копируешь эту статью себе на сайт, то оставляй ссылку непосредственно на эту страницу. Спасибо за понимание

Как просмотреть историю запросов в SQL Server Management Studio

Историю запросов можно просмотреть с помощью системных представлений:

  1. sys.dm_exec_query_stats
  2. sys.dm_exec_sql_text
  3. sys.dm_exec_query_plan

Например, используя следующий запрос:

 select top(100)
        создание_время,
        последнее_время_выполнения,
        количество_выполнений,
        total_worker_time/1000 в качестве процессора,
        конвертировать (деньги, (общее_время_работника))/(выполнение_счетчика*1000) как [AvgCPUTime],
        qs. total_elapsed_time/1000 как TotDuration,
        конвертировать(деньги, (qs.total_elapsed_time))/(выполнение_счетчик*1000) как [AvgDur],
        total_logical_reads как [Чтения],
        total_logical_writes как [Запись],
        total_logical_reads+total_logical_writes как [AggIO],
        конвертировать (деньги, (total_logical_reads + total_logical_writes)/(execution_count + 0.0)) как [AvgIO],
        [sql_handle],
        план_дескриптор,
        statement_start_offset,
        statement_end_offset,
        план_генерация_номер,
        общее_физическое_чтение,
        convert(money, total_physical_reads/(execution_count + 0.0)) as [AvgIOPhysicalReads],
        конвертировать (деньги, total_logical_reads/(execution_count + 0.0)) как [AvgIOLogicalReads],
        конвертировать (деньги, total_logical_writes/(execution_count + 0.0)) как [AvgIOLogicalWrites],
        запрос_хэш,
        query_plan_hash,
        всего_рядов,
        конвертировать (деньги, total_rows/(execution_count + 0. 0)) как [AvgRows],
        тотал_доп,
        конвертировать(деньги, total_dop/(выполнение_счетчик + 0.0)) как [AvgDop],
        total_grant_kb,
        конвертировать (деньги, total_grant_kb/(execution_count + 0.0)) как [AvgGrantKb],
        total_used_grant_kb,
        конвертировать (деньги, total_used_grant_kb/(execution_count + 0.0)) как [AvgUsedGrantKb],
        total_ideal_grant_kb,
        конвертировать (деньги, total_ideal_grant_kb/(execution_count + 0.0)) как [AvgIdealGrantKb],
        всего_зарезервированных_потоков,
        конвертировать (деньги, total_reserved_threads/(execution_count + 0.0)) как [AvgReservedThreads],
        общее количество_использованных_потоков,
        конвертировать (деньги, total_used_threads/(execution_count + 0.0)) как [AvgUsedThreads],
        кейс
            когда sql_handle IS NULL, тогда ' '
            иначе (подстрока (st.text, (qs.statement_start_offset + 2)/2, (
                кейс
                    когда qs.statement_end_offset =-1, тогда len(convert(nvarchar(MAX),st. text))*2
                    иначе qs.statement_end_offset
                конец - qs.statement_start_offset)/2 ))
        заканчиваться как query_text,
        db_name(st.dbid) как имя_базы_данных,
        object_schema_name(st.objectid, st.dbid)+'.'+object_name(st.objectid, st.dbid) как [object_name],
        sp.[план_запроса]
из sys.dm_exec_query_stats как qs с (readuncommitted)
перекрестное применение sys.dm_exec_sql_text(qs.[sql_handle]) как st
перекрестное применение sys.dm_exec_query_plan(qs.[plan_handle]) как sp
ГДЕ ст.[текст] НРАВИТСЯ '%query%'
 

Текущие запущенные запросы можно просмотреть с помощью следующего сценария:

 выберите ES.[session_id]
      ,ER.[blocking_session_id]
      ,ER.[request_id]
      ,ER.[start_time]
      ,DateDiff(секунда, ER.[start_time], GetDate()) как [date_diffSec]
      , СЛИЯТЬСЯ(
                    CAST(NULLIF(ER.[total_elapsed_time] / 1000, 0) как BIGINT)
                   ,CASE WHEN (ES.[status] <> 'работает' и isnull(ER.[status], '') <> 'работает')
                            THEN DATEDIFF(ss,0,getdate() - nullif(ES. [last_request_end_time], '1900-01-01T00:00:00.000'))
                    КОНЕЦ
                ) как [общее_время, сек]
      , CAST(NULLIF((CAST(ER.[total_elapsed_time] as BIGINT) - CAST(ER.[wait_time] AS BIGINT)) / 1000, 0 ) as bigint) as [work_time, sec]
      , CASE WHEN (ER.[статус] <> 'работает' AND ISNULL(ER.[статус],'') <> 'работает')
                THEN DATEDIFF(ss,0,getdate() - nullif(ES.[last_request_end_time], '1900-01-01T00:00:00.000'))
        END as [время сна, сек] --Время сна в сек
      , NULLIF( CAST((ER.[логические_чтения] + ER.[записи]) * 8/1024 как числовое (38,2)), 0) как [IO, МБ]
      , CASE ER.transaction_isolation_level
        КОГДА 0 ТОГДА 'Не указано'
        WHEN 1 THEN 'ReadUncommited'
        КОГДА 2, ТОГДА 'ReadCommited'
        КОГДА 3 ТОГДА 'Повторяющийся'
        КОГДА 4 ТОГДА "Сериализуемый"
        КОГДА 5 ТОГДА 'Снимок'
        ЗАВЕРШИТЬ как [transaction_isolation_level_desc]
      ,ER.[статус]
      ,ES.[status] как [status_session]
      ,ER.[команда]
      ,ER. [percent_complete]
      ,DB_Name(объединить(ER.[database_id], ES.[database_id])) как [DBName]
      , ПОДСТРОКА(
                    (выберите верхнюю часть (1) [текст] из sys.dm_exec_sql_text (ER. [sql_handle]))
                  , ER.[statement_start_offset]/2+1
                  , (
                        CASE WHEN ((ER.[statement_start_offset]<0) ИЛИ (ER.[statement_end_offset]<0))
                                THEN DATALENGTH ((выберите top(1) [text] из sys.dm_exec_sql_text(ER.[sql_handle])))
                             ИНАЧЕ ER.[statement_end_offset]
                        КОНЕЦ
                        - ER.[statement_start_offset]
                    )/2 +1
                 ) как [CURRENT_REQUEST]
      ,(выберите top(1) [текст] из sys.dm_exec_sql_text(ER.[sql_handle])) как [TSQL]
      ,(выберите top(1) [objectid] из sys.dm_exec_sql_text(ER.[sql_handle])) как [objectid]
      ,(выберите top(1) [query_plan] из sys.dm_exec_query_plan(ER.[plan_handle])) как [QueryPlan]
      , NULL as [event_info] -- (выберите top(1) [event_info] из sys. dm_exec_input_buffer(ES.[session_id], ER.[request_id])) as [event_info]
      ,ER.[wait_type]
      ,ES.[время_входа]
      ,ES.[host_name]
      ,ES.[имя_программы]
      ,cast(ER.[wait_time]/1000 как десятичное число(18,3)) как [wait_timeSec]
      ,ER.[время_ожидания]
      ,ER.[last_wait_type]
      ,ER.[wait_resource]
      ,ER.[open_transaction_count]
      ,ER.[open_resultset_count]
      ,ER.[идентификатор_транзакции]
      ,ER.[context_info]
      ,ER.[расчетное_время_завершения]
      ,ER.[cpu_time]
      ,ER.[total_elapsed_time]
      ,ER.[идентификатор_планировщика]
      ,ER.[task_address]
      ,ER.[читает]
      ,ER.[пишет]
      ,ER.[логические_чтения]
      ,ER.[text_size]
      ,ER.[язык]
      ,ER.[формат_даты]
      ,ER.[date_first]
      ,ER.[quoted_identifier]
      ,ER.[arithabort]
      ,ER.[ansi_null_dflt_on]
      ,ER.[ansi_defaults]
      ,ER.[ansi_warnings]
      ,ER.[ansi_padding]
      ,ER.[ansi_nulls]
      ,ER.[concat_null_yields_null]
      ,ER.[transaction_isolation_level]
      ,ER. [lock_timeout]
      ,ER.[deadlock_priority]
      ,ER.[row_count]
      ,ER.[prev_error]
      ,ER.[nest_level]
      ,ER.[предоставленная_запрос_память]
      ,ER.[executing_managed_code]
      ,ER.[group_id]
      ,ER.[query_hash]
      ,ER.[query_plan_hash]
      ,EC.[самый_последний_сеанс_id]
      ,EC.[connect_time]
      ,EC.[net_transport]
      ,EC.[тип_протокола]
      ,EC.[версия_протокола]
      ,EC.[endpoint_id]
      ,EC.[опция_шифрования]
      ,EC.[auth_scheme]
      ,EC.[node_affinity]
      ,EC.[num_reads]
      ,EC.[num_writes]
      ,EC.[last_read]
      ,EC.[last_write]
      ,EC.[net_packet_size]
      ,EC.[client_net_address]
      ,EC.[client_tcp_port]
      ,EC.[local_net_address]
      ,EC.[local_tcp_port]
      ,EC.[parent_connection_id]
      ,EC.[самая_последняя_sql_handle]
      ,ES.[host_process_id]
      ,ES.[client_version]
      ,ES.[client_interface_name]
      ,ES.[security_id]
      ,ES.[логин_имя]
      ,ES.[nt_domain]
      ,ES.[nt_user_name]
      ,ES. [memory_usage]
      ,ES.[total_scheduled_time]
      ,ES.[last_request_start_time]
      ,ES.[last_request_end_time]
      ,ES.[is_user_process]
      ,ES.[original_security_id]
      ,ES.[original_login_name]
      ,ES.[последний_успешный_вход]
      ,ES.[последний_неудачный_вход]
      ,ES.[неудачные_входы]
      ,ES.[идентификатор_базы_данных_аутентификации]
      ,ER.[sql_handle]
      ,ER.[statement_start_offset]
      ,ER.[statement_end_offset]
      ,ER.[plan_handle]
      ,NULL as [dop]--ER.[dop]
      ,объединить(ER.[идентификатор_базы_данных], ES.[идентификатор_базы_данных]) как [идентификатор_базы_данных]
      ,ER.[user_id]
      ,ER.[connection_id]
из sys.dm_exec_requests ER с (readuncommitted)
право присоединиться к sys.dm_exec_sessions ES с (readuncommitted)
на ES.session_id = ER.session_id
левое соединение sys.dm_exec_connections EC с (readuncommitted)
на EC.session_id = ES.session_id
где ER.[status] in («приостановлено», «выполняется», «работает»)
или существует (выберите top(1) 1 из sys. dm_exec_requests как ER0, где ER0.[blocking_session_id]=ES.[session_id])
 

Этот запрос отображает все активные запросы и все те запросы, которые явно блокируют активные запросы.

Все эти и другие полезные скрипты реализованы в виде представлений в базе данных SRV, которая распространяется бесплатно.
Например, первый скрипт получен из представления [inf].[vBigQuery], а второй — из представления [inf].[vRequests].

Существуют также различные сторонние решения для истории запросов.
Я использую Query Manager от Dbeaver:

и журнал выполнения запросов из инструментов SQL, встроенный в SSMS:

ssms — Как просмотреть выполненные запросы в SQL Server Management Studio?

спросил

Изменено
10 месяцев назад

Просмотрено
163 тыс. раз

Я новичок в SQL Server Management Studio, и мне интересно: есть ли способ увидеть, какие запросы были выполнены к базе данных?

В мониторе активности есть отчет «Последние дорогостоящие запросы», но я предполагаю, что это не все запросы, так как я не вижу тех, которые выполнял.

Я использую SQL Server Express 2008 v 10.0.1600.22.

  • ssms
  • SQL-сервер-экспресс

1

Используйте SQL Profiler и фильтруйте его, чтобы получить самые дорогие запросы.

2

Используйте монитор активности. Это последняя панель инструментов в верхней панели. Он покажет вам список «Последние дорогие запросы». Вы можете дважды щелкнуть их, чтобы увидеть план выполнения и т. д.

1

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

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

Вы можете сделать это с помощью команд DBCC LOG или fn_dblog или стороннего средства чтения журналов, такого как ApexSQL Log (обратите внимание, что инструмент предоставляется за определенную плату)

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

Вам нужен профилировщик SQL, который на самом деле работает вне SQL Management Studio. Если у вас есть платная версия SQL Server (например, версия для разработчиков), она должна быть включена в нее как еще одна утилита.

Если вы используете бесплатную версию (SQL Express), у них есть бесплатные профили, которые вы можете скачать. Я использовал профилировщик AnjLab (доступный по адресу http://sites.google.com/site/sqlprofiler), и он, похоже, работал хорошо.

0

Запустите следующий запрос из Management Studio для запущенного процесса:

 DBCC inputbuffer (spid#)
 

Это вернет SQL, который в настоящее время выполняется для базы данных для предоставленного SPID. Обратите внимание, что вам нужны соответствующие разрешения для запуска этой команды.

Это лучше, чем запуск трассировки, поскольку она нацелена на определенный SPID. Вы можете увидеть, долго ли он работает, основываясь на CPUTime и DiskIO.

Пример для получения сведений о SPID 64:

 DBCC inputbuffer(64)
 
 ВЫБЕРИТЕ * ИЗ sys.dm_exec_sessions es
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.dm_exec_connections ec
ON es.session_id = ec.session_id
ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ sys.dm_exec_sql_text(ec.most_recent_sql_handle), где es.session_id=65 в см.